一、给出 中序和先序 或者 中序和后序 还原树
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;
}