一、給出 中序和先序 或者 中序和後序 還原樹
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;
}