PAT甲级中关于树的一些题型的总结

一、给出 中序和先序 或者 中序和后序 还原树

1127 ZigZagging on a Tree (30 分)
题意
给定一棵树的中序和后序,折叠层序遍历整棵树。

/***********************
*author:ccf
*source:PAT-1127 ZigZagging on a Tree (30 ·Ö)
*topic:DS build tree
************************/
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <unordered_map>
#include <queue>
#include <vector>
#define ll long long
using namespace std;

const int N = 37;
int post[N],in[N],n,last = 1; 
struct Node{
	int val,layer;
	struct Node *lc,*rc;
}node; 
queue<Node> que;
unordered_map<int,int> mp;
vector<int> ans[37];
Node* Rebuild(int l,int r,int s,int e){
	if(s > e) return NULL;
	Node *root = new Node();
	root->val = post[r];
	int k;
	for(int i = s; i <= e; i++){
		if(in[i] == post[r]){
			k = i;
			break;
		}
	} 
	root->lc = Rebuild(l,r-e+k-1,s,k-1);
	root->rc = Rebuild(r-e+k,r-1,k+1,e);
	return root;
} 
int main(){
	//freopen("data.in","r",stdin);
	scanf("%d",&n);
	for(int i = 1; i <= n; i++) scanf("%d",in + i);
	for(int i = 1; i <= n; i++) scanf("%d",post+i);
	Node *root = new Node();
	root = Rebuild(1,n,1,n);
	root->layer  = 1;
	//printf("root = %d\n",root->val);
	que.push(*root);
	while(que.size()){
		node = que.front();
		int frt = node.val;
		ans[node.layer].push_back(frt);
		que.pop();
		if(!mp[frt]){
			mp[frt] = 1;
			if(node.lc != NULL){
				last = node.lc->layer = node.layer + 1;
				que.push(*node.lc);
			}
			if(node.rc != NULL){
				last = node.rc->layer = node.layer + 1;
				que.push(*node.rc);
			}
		}
	}
	//printf("last = %d\n",last);
	for(int i = 1; i <= last; i++){
		int len = ans[i].size();
		if(i & 1){
			for(int j = len - 1; j >= 0; j--){
				printf("%d",ans[i][j]);
				if(j != 0) printf(" ");
			}
		}else{
			for(int j = 0; j < len; j++){
				printf("%d",ans[i][j]);
				if(j != len-1) printf(" ");
			}
		}
		if(i != last) printf(" ");
	}
	return 0;
}

二、自平衡的BST树

AVL树

1066 Root of AVL Tree (25 分)
题意
给出一个插入序列,建成一颗AVL树,输出AVL树的根结点的值。

/***********************
*author:ccf
*source:PAT-1066 Root of AVL Tree
*topic:AVL的维护
************************/
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <vector>
#define ll long long
using namespace std;

struct Node {
	int val,id,height;
	struct Node *lc,*rc;
};
const int N = 107;
int tree[N];
int n,a;
queue<Node> que;
vector<int> ans;

void debug(Node* root) {
	if(root == NULL) return ;
	printf("%d ",root->val);
	debug(root->lc);
	debug(root->rc);
}
//得到高度 
int Get_hei(Node* root) {
	if(root == NULL) return 0;
	return root->height;
}
//更新高度 
void Update_hei(Node* root) {
	root->height = max(Get_hei(root->lc), Get_hei(root->rc)) + 1;
}
//获得平衡因子 
int Get_balan(Node* root){
	return Get_hei(root->rc) - Get_hei(root->lc);
}
//左左型  右单旋
Node* LL(Node* root) {
	Node* newroot = root->lc;
	root->lc = newroot->rc;
	newroot->rc = root;
	Update_hei(root);
	Update_hei(newroot);
	return newroot;
}
//右右型  左单旋
Node* RR(Node* root) {
	Node* newroot = root->rc;
	root->rc = newroot->lc;
	newroot->lc = root;
	Update_hei(root);
	Update_hei(newroot) ;
	return newroot; 
}
//左右型    先左旋 再右旋
Node* LR(Node* root) {
	root->lc = RR(root->lc);
	return LL(root);
}
//右左型    先右旋  再左旋
Node* RL(Node* root) {
	root->rc = LL(root->rc);
	return RR(root);
}
//将x插入到AVL树中  并返回根节点
Node* Insert(Node* root ,int x) {
	if(root == NULL) {
		root = new Node();
		root->val = x;
		root->lc = root->rc = NULL;
		root->height = 1;
	} else if(x < root->val) {
		root->lc=Insert(root->lc,x);
		if(Get_balan(root) == -2) {
			if(x < root->lc->val) root = LL(root);
			else root = LR(root);
		}
	} else if(x > root->val) {
		root->rc = Insert(root->rc,x);
		if(Get_balan(root) == 2){
			if(x > root->rc->val) root = RR(root);
			else root = RL(root);
		}
	}
	Update_hei(root);
	return root;
}

int main() {
	//freopen("data.in","r",stdin);
	//建树
	Node *root = NULL;
	scanf("%d",&n);
//	printf(" n = %d\n",n);
	for(int i = 1; i <= n; i++) {
		scanf("%d",&a);
//		printf("%d ",a);
		root = Insert(root,a);
	} 
	//层序遍历
//	root->id = 1;
//	que.push(*root);
//	while(que.size()){
//		Node f = que.front();
//		ans.push_back(f.val);
//		tree[f.id] = 1;
//		que.pop();
//		if(f.lc != NULL){
//			f.lc->id = 2*f.id;
//			que.push(*f.lc);
//		}
//		if(f.rc != NULL){
//			f.rc->id = 2*f.id + 1;
//			que.push(*f.rc);
//		}
//	}
//	int len = ans.size();
//	for(int i = 0 ; i < len; i++){
//		printf("%d",ans[i]);
//		if(i != len - 1) printf("#");
//		else printf("\n");
//	}
//	//判断是否完全
//	for(int i = 1; i <= n; i++){
//		if(tree[i] == 0){
//			printf("NO");
//			return 0;
//		}
//	}
//	printf("YES");
	printf("%d",root->val); 
	return 0;
}

1123 Is It a Complete AVL Tree (30 分)
题意
给定一个插入序列,建成一颗AVL树,输出AVL树的层序遍历,并判断AVL是否是一颗完全二叉树,是输出"YES",否则输出"NO";

/***********************
*author:ccf
*source:PAT-1123 Is It a Complete AVL Tree (30 分)
*topic:AVL的维护
************************/
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <vector>
#define ll long long
using namespace std;

struct Node {
	int val,id,height;
	struct Node *lc,*rc;
};
const int N = 107;
int tree[N];
int n,a;
queue<Node> que;
vector<int> ans;

void debug(Node* root) {
	if(root == NULL) return ;
	printf("%d ",root->val);
	debug(root->lc);
	debug(root->rc);
}
//得到高度 
int Get_hei(Node* root) {
	if(root == NULL) return 0;
	return root->height;
}
//更新高度 
void Update_hei(Node* root) {
	root->height = max(Get_hei(root->lc), Get_hei(root->rc)) + 1;
}
//获得平衡因子 
int Get_balan(Node* root){
	return Get_hei(root->rc) - Get_hei(root->lc);
}
//左左型  右单旋
Node* LL(Node* root) {
	Node* newroot = root->lc;
	root->lc = newroot->rc;
	newroot->rc = root;
	Update_hei(root);
	Update_hei(newroot);
	return newroot;
}
//右右型  左单旋
Node* RR(Node* root) {
	Node* newroot = root->rc;
	root->rc = newroot->lc;
	newroot->lc = root;
	Update_hei(root);
	Update_hei(newroot) ;
	return newroot; 
}
//左右型    先左旋 再右旋
Node* LR(Node* root) {
	root->lc = RR(root->lc);
	return LL(root);
}
//右左型    先右旋  再左旋
Node* RL(Node* root) {
	root->rc = LL(root->rc);
	return RR(root);
}
//将x插入到AVL树中  并返回根节点
Node* Insert(Node* root ,int x) {
	if(root == NULL) {
		root = new Node();
		root->val = x;
		root->lc = root->rc = NULL;
		root->height = 1;
	} else if(x < root->val) {
		root->lc=Insert(root->lc,x);
		if(Get_balan(root) == -2) {
			if(x < root->lc->val) root = LL(root);
			else root = LR(root);
		}
	} else if(x > root->val) {
		root->rc = Insert(root->rc,x);
		if(Get_balan(root) == 2){
			if(x > root->rc->val) root = RR(root);
			else root = RL(root);
		}
	}
	Update_hei(root);
	return root;
}

int main() {
	//freopen("data.in","r",stdin);
	//建树
	Node *root = NULL;
	scanf("%d",&n);
//	printf(" n = %d\n",n);
	for(int i = 1; i <= n; i++) {
		scanf("%d",&a);
//		printf("%d ",a);
		root = Insert(root,a);
	} 
	//层序遍历
	root->id = 1;
	que.push(*root);
	while(que.size()){
		Node f = que.front();
		ans.push_back(f.val);
		tree[f.id] = 1;
		que.pop();
		if(f.lc != NULL){
			f.lc->id = 2*f.id;
			que.push(*f.lc);
		}
		if(f.rc != NULL){
			f.rc->id = 2*f.id + 1;
			que.push(*f.rc);
		}
	}
	int len = ans.size();
	for(int i = 0 ; i < len; i++){
		printf("%d",ans[i]);
		if(i != len - 1) printf(" ");
		else printf("\n");
	}
	//判断是否完全
	for(int i = 1; i <= n; i++){
		if(tree[i] == 0){
			printf("NO");
			return 0;
		}
	}
	printf("YES");
	return 0;
}

红黑树

1135 Is It A Red-Black Tree (30 分)
题意
给出红黑树的一些性质,问一颗二叉搜索树是否是一个红黑树,是就输出"Yes",否则输出"No"。

(1) 每个点不是红就是黑
(2) 根是黑的
(3) 每个叶子 (包括NULL) 是黑的
(4) 如果结点是红的,那么其孩子结点是黑的
(5) 对于每个结点,其到其子树上的任意一个叶子结点的路径中的黑色结点个数相同。
/***********************
*author:ccf
*source:
*topic:build tree
************************/
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define ll long long
using namespace std;

int cas,n;
struct Node {
	int val;
	struct Node *lc,*rc;
};
int a[37];
//建树
Node* build(Node *root,int v) {
	if(root == NULL) {
		root = new Node();
		root->val = v;
		root->lc = NULL;
		root->rc = NULL;
	} else if(abs(v) <= abs(root->val)) {
		root->lc = build(root->lc,v);
	} else {
		root->rc = build(root->rc,v);
	}
	return root;
}
//结点是红的,它的孩子是黑的
bool check1(Node *root) {
	if(root == NULL) return true;
	if(root->val < 0) { //红色
		if(root->lc != NULL && root->lc->val < 0) return false;
		if(root->rc != NULL && root->rc->val < 0) return false;
	}
	return check1(root->lc) && check1(root->rc);
}
//每个结点 它到子树的叶节点中黑色的结点个数相同
int get_black(Node *root) {
	if(root == NULL) {
		return 0;
	}
	int res = max(get_black(root->lc),get_black(root->rc));
	if(root->val > 0) {
		return  res+ 1;
	} else
		return res;
}
bool check2(Node *root) {
	if(root == NULL) {
		return true;
	}
	int lb = get_black(root->lc),rb = get_black(root->rc);
	if(lb != rb) return false;
	return check2(root->lc) && check2(root->rc);
}
int main() {
	//freopen("data.in","r",stdin);
	scanf("%d",&cas);
	Node *root;
	while(cas--) {
		root = NULL;
		scanf("%d",&n);
		for(int i = 0 ; i < n; i++) {
			scanf("%d",a + i);
			root = build(root,a[i]);
		}
		if(a[0] < 0 || !check1(root) || !check2(root)) {
			printf("No\n");
		} else
			printf("Yes\n");
	}

	return 0;
}

发布了141 篇原创文章 · 获赞 71 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/sinat_40872274/article/details/103219181
今日推荐