0
点赞
收藏
分享

微信扫一扫

PAT----树----BST+AVL

zhyuzh3d 2022-03-11 阅读 76
算法

————————————————————————————————

BST

————————————————————————————————

BST的插入建立,镜像

1043

// 1.BST的建立: 空指针开始, 插入函数:赋值函数+递归调用,
// 2.树的镜像:遍历的时候对换左右孩子节点的顺序就好
// 3.两个vector可以直接比较

//核心: 单序列建BST  +   树的镜像BST 

//1.单序列建BST:  
//				(1)BST树的创建只需要一个插入序列即可 
//				(2)struct node:  带参数的构造函数 
//				(3)for()输入插入   +   insert(node*& root, int x)    !!!!一定注意第一个参数的类型哦 
//			  (4)insert:  
//								1)root==nullptr:  新建一个节点返回 
//								2)x<root->value:  insert(root->left)  //直接调用, 没有赋值哦 
//								3)x>=root->value:  insert(root->right)  //直接调用, 没有赋值哦 
//				(5)注意和两序列建树的辨析 

//2.树的镜像:  建树的时候正常, 访问的时候左右节点掉换即可  

//3.Debug:   F11单步调试----检查建树是否成功比较有用, 其他直接打印即可   

#include <iostream>
#include <vector>

using namespace std;


struct node{
	int value;
	node *left, *right;

	node(int x) {
		value = x;
		left = nullptr;
		right = nullptr;
	}
};

int n,flag;
vector<int>inputs, pre, preM;

void insert(node*& root, int x) {
	if (root == nullptr) {
		root = new node(x);
		return;
	}

	//cout << "Come Here?" << endl;

	if (x < root->value)insert(root->left, x);
	else if (x >= root->value)insert(root->right, x);
	//return root;
}

void preOrder(node* root) {
	if (root == nullptr)return;

	pre.push_back(root->value);
	preOrder(root->left);
	preOrder(root->right);
}

void preOrderM(node* root) {
	if (root == nullptr)return;

	preM.push_back(root->value);
	preOrderM(root->right);
	preOrderM(root->left);
}

void postOrder(node* root) {
	if (root == nullptr)return;

	postOrder(root->left);
	postOrder(root->right);
	if (flag == 0) {
		flag = 1;
		printf("%d", root->value);
	}
	else printf(" %d", root->value);
}

void postOrderM(node* root) {
	if (root == nullptr)return;

	postOrderM(root->right);
	postOrderM(root->left);
	if (flag == 0) {
		flag = 1;
		printf("%d", root->value);
	}
	else printf(" %d", root->value);
}


int main() {
	scanf("%d", &n);
	node* root = nullptr;
	for (int i = 0; i < n; i++) {
		int tmp;
		scanf("%d", &tmp);
		insert(root, tmp);
		inputs.push_back(tmp);
	}

	preOrder(root);
	preOrderM(root);

	if (inputs == pre) {
		printf("YES\n");
		flag = 0;
		postOrder(root);
		printf("\n");
	}
	else if (inputs == preM) {
		printf("YES\n");
		flag = 0;
		postOrderM(root);
		printf("\n");
	}
	else printf("NO\n");

	return 0;
}

BST的插入建立, 层数记录

1115

方法一:   BST建树+BFS

//核心:  BST单序列建树  +  BFS处理每一层 

//1.BST单序列建树:  
//			(1)struct node:和构造函数 
//			(2)insert函数:
//							1)参数:  !!(node*&root, int x) 
//							2)如果 root==nullptr:  新建节点 + return 
//							3)x<=root->value:  insert(root->left, x); 
//							4)x>root->value:  insert(root->right, x); 
//			(3)for(){ insert(root, x); }

//2.BFS处理每一层:nullptr的运用  

//3.!!!自己设计, 自己思考特殊样例成功:    在看到题的时候, 对某些逻辑和情况有疑虑就记录下来, 没准Debug的时候有用  


#include <iostream>
#include <queue>

using namespace std;

struct node{
	int value;
	node *left, *right;
	node(int x) {
		value = x;
		left = nullptr;
		right = nullptr;
	}
};

int n;
vector<int>counts;

void insert(node*& root, int x) {
	if (root == nullptr) {
		root = new node(x);
		return;
	}

	if (x <= root->value)insert(root->left, x);
	else insert(root->right, x);
}

void BFS(node* root) {
	queue<node*>q;
	q.push(root);
	q.push(nullptr);
	int cnt = 0;

	while(!q.empty()) {
		node* current = q.front();
		q.pop();



		if (current == nullptr) {
			counts.push_back(cnt);
			//cout <<"###cnt: " <<cnt << endl;
			cnt = 0;
			if (!q.empty())q.push(nullptr);
		}
		else {
			cnt++;

			//cout << "Come here?" << endl;
			if (current->left != nullptr)q.push(current->left);
			if (current->right != nullptr)q.push(current->right);
		}

	}

}

//void preOrder(node* root) {
//	if (root == nullptr)return;
//
//	cout << root->value<<" "<< endl;
//	preOrder(root->left);
//	preOrder(root->right);
//}

int main() {
	scanf("%d", &n);
	node* root = nullptr;
	for (int i = 0; i < n; i++) {
		int tmp;
		scanf("%d", &tmp);
		insert(root, tmp);
	}

	//preOrder(root);

	BFS(root);

	//cout <<"####" <<counts.size() << endl;
	//for (int i = 0; i < counts.size(); i++)cout << counts[i] << " ";
	//cout << endl;


	if (counts.size() >= 2) {
		int a, b;
		a = counts[counts.size() - 1];
		b = counts[counts.size() - 2];
		printf("%d + %d = %d", counts[counts.size() - 1], counts[counts.size() - 2], a + b);
	}
	else if (counts.size() == 1) {
		printf("%d + 0 = %d", counts[counts.size() - 1], counts[counts.size() - 1]);
	}

	return 0;
}

 方法二:建树时节点维护layer变量, 遍历时记录最大两个layer的数量

(有时间, 自己试一遍喽)

// 1.和最常用的函数重名的变量名最好不要取, PAT的编译器不过
// 2.BST插入建树的时候, 如果有部分样例不过, 记得>=和<=
// 3.再次熟练BST的insert函数:如果==nullprt就新建, !=则叶子等于左查, 右叶子等于右插
// 4.nowNode的写法
// 5.积累BST建树的时候记录层数的功能
// 6.prinf的便利

//#include <bits/stdc++.h>
#include <iostream>

using namespace std;

int Max=0, cnt1=0, cnt2=0;

struct node {
	int data, layer;
	node*left;
	node*right;
};

node* newNode(int x, int depth){
	node* tmp = new node;
	tmp->data = x;
	tmp->layer = depth;
	tmp->left = nullptr;
	tmp->right = nullptr;

	return tmp;
}



node* insert(node*& root, int x, int depth){  //这里不加会怎么样
	if (root == nullptr) {
		root = newNode(x, depth);
		if (depth > Max)Max = depth;

		return root;
	}

	if (x <= root->data) {
		root->left = insert(root->left, x, depth + 1);
	}
	else if (x > root->data) {
		root->right = insert(root->right, x, depth + 1);
	}
	return root;
}

void inOrder(node* root) {
	if (root == nullptr) return;

	inOrder(root->left);
	if (root->layer == Max)cnt1++;
	else if (root->layer == (Max - 1))cnt2++;

	inOrder(root->right);
	
	return;
}

int main() {

	int nums;
	cin >> nums;

	node*root=nullptr;
	for (int i = 0; i < nums; i++) {
		int tmp;
		cin >> tmp;
		insert(root, tmp, 0);
	}

	inOrder(root);

	printf("%d + %d = %d", cnt1, cnt2, cnt1 + cnt2);

	return 0;
}

完全BST的中序建立

1064

// 1.BST的中序遍历是插入序列的排序
// 2.用中序序列建立BST(常用数组): 递归终止条件root的值大存储节点的index, 递归传tree,input,index,root
// 3.BST的层序遍历就是tree的顺序访问
// 4.vector可以使用algortihm里面的sort(v.begin(),v.end())进行访问


//核心:  完全BST的中序建树BST 
//1.BST的中序遍历, 是个排序
//2.如果知道完全二叉树的某种访问序列, 就可以用这个序列建树:
//				(1)参数:  root,  index 
//				(2)递归终止条件:  root> 序列.size()-1 
//				(3)干活:  tree[root]=序列[index++]  
//				(4)递归:  root的参数:    2*(root+1)+1,    2*(root+1)
//  			(5)场外: root, index 
//3.完全二叉树用数组装树, 顺序访问就是层序遍历 


#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int n;
vector<int>inputs, tree;

void inOrder(int root,  int &index) {
	if (root > (inputs.size() - 1))return;

	inOrder(2*(root+1)-1, index);
	tree[root] = inputs[index++];
	inOrder(2*(root + 1), index);

}

int main() {
	scanf("%d", &n);
	inputs.resize(n);
	tree.resize(n);
	for (int i = 0; i < n; i++) scanf("%d", &inputs[i]);
	sort(inputs.begin(), inputs.end());

	int index = 0;
	inOrder(0,index);

	for (int i = 0; i < tree.size(); i++) {
		if (i != 0)printf(" ");
		printf("%d", tree[i]);
	}

	return 0;
}

数组型BST的中序建立,层序输出

1099

// 1.核心: 用中序遍历建立BST
// 2.数组型树中序遍历建立BST的inOrder直接用左右叶子, 直接是数组的用2*(root+1)-1和2*root表示
// 3.函数能否用和头文件的位置也有关系
// 4.(就是前面知识点的组合, 不难, 都是一次过的嘛)

//核心:  数组建树 + 中序遍历给BST赋值 + 层序遍历输出BST 
//1.数组建树: 
//				(1)动手过样例:  根据下标画树 
//				(2)数据结构: struct node{}  +    vector<node>tree 
//				(3)访问, 动作:  和普通的节点树一样
//				(4)!!!常常会说 index=0是根, 所以做题的时候注意审题, 不必浪费不必要的时间寻找根
//2.中序遍历给BST赋值: 
//				(1)sort 
//				(2)int index=0;     inOrder(0, index);
//				(3)递归终止条件:   分数据结构:  数组型树,  数组树 不同 
//				(4)递归调用: 
//        				左边:inOrder(2*(root+1)-1, &index)
//								右边:inOrder(2*(root+1), &index)
//				(5)干活: tree[root].value= inputs[index++]
//3.层序遍历输出

//4.BST建法: 
//			 (1)insert 
//			 (2)sort + inOrder 


#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>

using namespace std;

struct node {
	int value, left, right;
};

int n;
vector<node>tree;
vector<int>inputs;

void inOrder(int root, int &index) {
	if (root == -1)return;

	inOrder(tree[root].left, index);
	tree[root].value = inputs[index++];
	inOrder(tree[root].right, index);

}

void leverOrder(int root) {
	queue<int>q;
	q.push(root);
	int flag = 0;

	while (!q.empty()) {
		int current = q.front();
		q.pop();

		if (!flag) {
			flag = 1;
			printf("%d", tree[current].value);
		}else printf(" %d", tree[current].value);

		if (tree[current].left != -1)q.push(tree[current].left);
		if (tree[current].right != -1)q.push(tree[current].right);
	}
}

int main() {
	scanf("%d", &n);
	inputs.resize(n);
	for (int i = 0; i < n; i++) {
		node nodeTmp;
		scanf("%d %d", &nodeTmp.left, &nodeTmp.right);
		tree.push_back(nodeTmp);
	}
	for (int i = 0; i < n; i++)scanf("%d", &inputs[i]);
	sort(inputs.begin(), inputs.end());

	int index = 0;  //因为有&, 所以这里必须在外面声明
	inOrder(0,index);

	leverOrder(0);

	return 0;
}

BST的前序建立+DFS+红黑树的判断(可以背代码块)

1135

//1.红黑树:
    // (1)是BST
    // (2)根节点是黑色
    // (3)NULL是黑色
    // (4)红色节点两个孩子是黑色
    // (5)任意节点到叶子节点, 黑色节点数相等
//2.如果是BST:只要给一个序列就可以建树
// 3.积累  BST建树
// 4.积累 树DFS的写法和用处:
//     (1)写法:
//         1)递归终止条件, 
//         2)该节点的处理(计数, 节点数值判断, 左右孩子判断等)
//         3)递归
//         4)并且可以带返回值
//     (2)用处:记录层数, 特殊节点计数



//核心:    BST的单序列建树  +   红黑树的判断(可以背代码块)
//1.BST的单序列建树:  
//						(1)node 构造函数 
//						(2)insert(root*&, int x)
//						(3)for()  insert 
//2.红黑树的判断:   
//						(1)三个条件: 
//									1)递归外:  root->value >0 
//									2) 到叶子节点的黑节点数量相等, 注意参数sum (有&和没&的区别:  有则值按整个顺序来, 没有下一个参数就是这次处理的值)
//									3)红色节点的两个孩子必须是黑色

//3.参数 有&和没&的区别

//4.熟练运用断点调试, 单步调试


#include <iostream>
#include <vector>
#include <cmath>

using namespace std;

int k, n, cntBlack = 0;

struct node {
	int value;
	node *left, *right;
	node(int x) {
		value = x;
		left = right = nullptr;
	}
};

void insert(node*& root, int x) {
	if (root == nullptr) {
		root = new node(x);
		return;
	}

	if (abs(x) <= abs(root->value))insert(root->left, x);   //这里题目没说==, 看情况
	else if (abs(x) > abs(root->value))insert(root->right, x);

}

bool isRedBlack(node* root, int sum) {
	if (root == nullptr) {
		if (cntBlack == sum)return true;
		else return false;
	}
	
	if (root->value > 0)sum++;
	else {
		if (root->left != nullptr && (root->left->value < 0))return false;
		if (root->right != nullptr && (root->right->value < 0))return false;
	}

	return isRedBlack(root->left, sum) && isRedBlack(root->right, sum);
}

int main() {
	scanf("%d", &k);
	while (k--) {

		//建树
		scanf("%d", &n);
		node* root = nullptr;
		for (int i = 0; i < n; i++) {
			int tmp;
			scanf("%d", &tmp);
			insert(root, tmp);
		}
	
		//判断是否红黑树
		node *tmpNode = root;
		cntBlack = 0;
		while (tmpNode != nullptr) {
			if (tmpNode->value > 0)cntBlack++;
			tmpNode = tmpNode->left;
		}
		int sum = 0;
		bool flag = (root->value>0)&&isRedBlack(root,sum);

		if (flag)printf("Yes\n");
		else printf("No\n");
	
	}

	return 0;
}

————————————————————————————————

AVL

————————————————————————————————

AVL建树(AVL标准模板)

1066 

//核心:  AVL建树 
//AVL检查的好办法: 注释掉AVL的部分, 只检查BST;


#include<iostream>
#include<vector>
#include<algorithm>


using namespace std;

struct node {
	int value;
	node *left, *right;

	node(int x) {
		value = x;
		left = nullptr;
		right = nullptr;
	}
};

int n;
node* root=nullptr;

int getHeight(node* tree) {
	if (tree == nullptr)return 0;

	int l = getHeight(tree->left);
	int r = getHeight(tree->right);

	return max(l, r) + 1;
}

node* leftRotate(node* tree) {
	node* tmp = tree->right;
	tree->right = tmp->left;
	tmp->left = tree;
	return tmp;
}

node* rightRotate(node* tree) {
	node* tmp = tree->left;
	tree->left = tmp->right;
	tmp->right = tree;
	return tmp;
}

node* lrRotate(node* tree) {
	tree->left = leftRotate(tree->left);
	return rightRotate(tree);
}

node* rlRotate(node* tree) {
	tree->right = rightRotate(tree->right);
	return leftRotate(tree);
}

node* insert(node* &tree, int x) {
	if (tree == nullptr) {
		tree = new node(x);
		return tree;
	}

	if (tree->value > x) {
		insert(tree->left, x);
		int l = getHeight(tree->left);
		int r = getHeight(tree->right);
		if ((l - r) >= 2) {
			if (x < tree->left->value)tree = rightRotate(tree);
			else tree = lrRotate(tree);
		}
	}
	else if (tree->value <= x) {
		insert(tree->right, x);
		int l = getHeight(tree->left);
		int r = getHeight(tree->right);
		if ((r - l) >= 2) {
			if (x > tree->right->value)tree = leftRotate(tree);
			else tree = rlRotate(tree);
		}
	}
	return tree;
}

//void preOrder(node* tree) {
//	if (tree == nullptr)return;
//
//	printf("%d ", tree->value);
//	preOrder(tree->left);
//	preOrder(tree->right);
//}


int main() {
	scanf("%d", &n);
	for (int i = 0; i < n; i++) {
		int tmp;
		scanf("%d", &tmp);
		root = insert(root, tmp);
	}

	//preOrder(root);
	//printf("\n");

	printf("%d", root->value);

	return 0;
}

AVL建树+判断完全二叉树+层序遍历

1123

//核心: AVL建立平衡二叉树 + 判断是否平衡二叉树 + 层序遍历输出  


//1.AVL: 
//      (1)理解AVL的本质: 就是BST, 在插入的时候分情况
//      (2)数据结构: 树:一般是node*的形式 
//      (3)操作:  
//          1)建树:  输入 + insert(node* &root, int x);
//          2)其他如普通树的操作 
//      (4)函数: 
//          1)int getHeight(node* tree){
//              if(tree==nullptr)return 0;
//               int l=getHeight(tree->left);
//               int r=getHeight(tree->right);
//               return max(l, r)+1;
//          }
//              
//          2)node* leftRotate(node* tree){
//              node* tmp=tree->right;  //哪边有获得哪边 
//              tree->right=tmp->left;  //原本的位置补一个空缺
//              tmp->left=tree;  //什么叫左旋
//              return tmp;  
//          }
//          3)node* rightRotate(node* tree){
//              node* tmp=tree->left;  //哪边有获得哪边 
//              tree->left=tmp->right;  //原本的位置补一个空缺 
//              tmp->right=tree;  //什么叫右旋 
//              return tmp;  
//          }
//
//          4)lrRotate(node* tree){
//              tree->left=leftRotate(tree->left);
//              return rightRotate(tree);
//          }
//          5)rlRotate(node* tree){
//              tree->right=rightRotate(tree->right);
//              return leftRotate(tree);
//          }
//          6)insert(node* &tree, int x){
//              if(tree==nullptr){
//                  tree=new node(x);
//                  return tree;
//              }
//              if(tree->value>x){
//                  insert(tree->left, x);
//                  int l=getHeight(tree->left);
//                  int r=getHeight(tree->right);
//                  if((l-r)>=2){
//                      if(x<tree->left->value)rightRotate(tree);
//                      else tree=lrRotate(tree);
//                      }
//              }
//              if(tree->value<x){
//                  insert(tree->right,x);
//                  int l=getHeight(tree->left);
//                  int r=getHeight(tree->right);
//                  if((r-l)>=2){
//                      if(x>tree->right->value)leftRotate(tree);
//                      else tree=rlRotate(tree);
//                  }
//              }
//              return tree;
//          }


//2.判断一棵树是否平衡二叉树: 
//      (1)特殊样例: 根节点: 左没有, 右有: flag==2;
//      (2)if else 语句判别


//3.结尾多一个“\n”也会PE, 没有“\n”会WA


#include<iostream>
#include<vector>
#include<unordered_map>
#include<set>
#include<queue>
#include<algorithm>

using namespace std;

struct node {
	int value;
	node *left, *right;

	node(int x) {
		value = x;
		left = nullptr;
		right = nullptr;
	}
};


int n, flag=0;
node* root=nullptr;

int getHeight(node *tmpRoot) {
	if (tmpRoot == nullptr)return 0;
	int l = getHeight(tmpRoot->left);
	int r = getHeight(tmpRoot->right);

	return max(l, r) + 1;  
}


node* leftRotate(node* tmpRoot) {
	node* tmp = tmpRoot->right;
	tmpRoot->right = tmp->left;
	tmp->left = tmpRoot;

	return tmp;
}


node* rightRotate(node* tmpRoot) {
	node* tmp = tmpRoot->left;
	tmpRoot->left = tmp->right;
	tmp->right = tmpRoot;

	return tmp;
}

node* rlRotate(node* tmpRoot) {
	tmpRoot->right = rightRotate(tmpRoot->right);
	return leftRotate(tmpRoot);
}


node* lrRotate(node* tmpRoot) {
	tmpRoot->left = leftRotate(tmpRoot->left);
	return rightRotate(tmpRoot);

}

node* insert(node* &tmpRoot, int tmp) {
	if (tmpRoot == nullptr) {
		tmpRoot = new node(tmp);
		return tmpRoot;
	}

	if (tmpRoot->value > tmp) {
		tmpRoot->left=insert(tmpRoot->left, tmp);
		int l = getHeight(tmpRoot->left);
		int r = getHeight(tmpRoot->right);
		if ((l - r) >= 2) {
			if (tmp < tmpRoot->left->value)tmpRoot = rightRotate(tmpRoot);
			else tmpRoot = lrRotate(tmpRoot);
		}
	}
	else if (tmpRoot->value <= tmp) {
		tmpRoot->right=insert(tmpRoot->right, tmp);
		int l = getHeight(tmpRoot->left);
		int r = getHeight(tmpRoot->right);
		if ((r - l) >= 2) {
			if (tmp > tmpRoot->right->value) tmpRoot = leftRotate(tmpRoot);
			else tmpRoot = rlRotate(tmpRoot);
		}
	}
	return tmpRoot;
}

void levelOrder(node* tmpRoot) {
	queue<node*>q;
	q.push(tmpRoot);

	if (tmpRoot->left == nullptr && (tmpRoot->right != nullptr))flag = 2;

	while (!q.empty()) {
		node* current = q.front();
		q.pop();
		if (current != tmpRoot)printf(" ");
		printf("%d",current->value);

		if (flag == 0 && (current->left == nullptr || current->right == nullptr))flag = 1;
		else if (flag == 1 && (current->left != nullptr || current->right != nullptr))flag = 2;

		if (current->left != nullptr)q.push(current->left);
		if (current->right != nullptr)q.push(current->right);

	}

	printf("\n");
	if (flag == 2)printf("NO");
	else printf("YES");

}





int main() {
	scanf("%d", &n);
	for (int i = 0; i < n; i++) {
		int tmp;
		scanf("%d", &tmp);
		
		root = insert(root, tmp);
	}


	levelOrder(root);
	printf("\n");


	return 0;
}

举报

相关推荐

0 条评论