7-28 搜索樹判斷 (25 分)
對於二叉搜索樹,我們規定任一結點的左子樹僅包含嚴格小於該結點的鍵值,而其右子樹包含大於或等於該結點的鍵值。如果我們交換每個節點的左子樹和右子樹,得到的樹叫做鏡像二叉搜索樹。
現在我們給出一個整數鍵值序列,請編寫程序判斷該序列是否爲某棵二叉搜索樹或某鏡像二叉搜索樹的前序遍歷序列,如果是,則輸出對應二叉樹的後序遍歷序列。
輸入格式:
輸入的第一行包含一個正整數N(≤1000),第二行包含N個整數,爲給出的整數鍵值序列,數字間以空格分隔。
輸出格式:
輸出的第一行首先給出判斷結果,如果輸入的序列是某棵二叉搜索樹或某鏡像二叉搜索樹的前序遍歷序列,則輸出YES,否側輸出NO。如果判斷結果是YES,下一行輸出對應二叉樹的後序遍歷序列。數字間以空格分隔,但行尾不能有多餘的空格。
輸入樣例1:
7
8 6 5 7 10 8 11
輸出樣例1:
YES
5 7 6 8 11 10 8
輸入樣例2:
7
8 6 8 5 10 9 11
輸出樣例2:
NO
剛開始沒搞懂這題這麼回事,給出一個序列,還要判斷是不是一個搜索樹的先序遍歷。
後來想明白了,要是先序遍歷序列,按照順序插入搜索樹就可以構成一顆搜索樹,然後再輸出前序和所給對比。
鏡像搜索樹有個特點:
1.鏡像後序序列的倒序與正常先序序列相同
2.正常後序序列的倒序與鏡像先序序列相同
AC代碼:
#include<stdio.h>
typedef struct node {
int data;
struct node *lchild, *rchild;
}Node, *Tree;
void insert(Tree &root,int x) {
if (root == NULL) {
root = new Node;
root->lchild = root->rchild = NULL;
root->data = x;
} else if (x < root->data) {
insert(root->lchild, x);
} else {
insert(root->rchild, x);
}
}
Tree create(int n,int buf[]) {
Tree root = NULL;
for (int i = 1; i <= n; i++) {
scanf("%d", &buf[i]);
insert(root, buf[i]);
}
return root;
}
void preorder(Tree root,int pre[],int &i) {
if (root == NULL)return;
pre[i++] = root->data;
preorder(root->lchild, pre, i);
preorder(root->rchild, pre, i);
}
void posorder(Tree root, int pos[], int &i) {
if (root == NULL)return;
posorder(root->lchild, pos, i);
posorder(root->rchild, pos, i);
pos[i++] = root->data;
}
bool issma(int a[], int b[], int n,bool rvs) {
for (int i = 1; i <= n; i++) {
if (rvs) {
int j = n - i + 1;
if (a[i] != b[j])return false;
} else {
if (a[i] != b[i])return false;
}
}
return true;
}
void show(int order[], int n, bool rvs) {
bool first = true;
for (int i = 1; i <= n; i++) {
if (first)
first = false;
else
printf(" ");
if (rvs) {
int j = n + 1 - i;
printf("%d", order[j]);
} else {
printf("%d", order[i]);
}
}
}
int main() {
int n;
scanf("%d", &n);
int buf[1001], pre[1001], pos[1001];
Tree root;
root = create(n, buf);
int i = 1, j = 1;
preorder(root, pre, i);//先序遍歷
posorder(root, pos, j);//後序遍歷
//通過觀察有以下規律:規律1.鏡像後序遍歷的倒序與正常先序相同;規律2.正常後序的倒序與鏡像先序相同
if (issma(buf, pre, n,false)) {//先序遍歷與所給序列一致
printf("YES\n");
show(pos, n, false);
} else if(issma(buf, pos, n, true)){//若是鏡像二叉樹,則所給序列是該序列對應二叉樹後序遍歷的倒序(規律2)
printf("YES\n");
show(pre, n, true);//鏡像的後序就爲正常先序的倒序(規律1)
} else {
printf("NO\n");
}
}
這代碼量算比較少得了,沒想到一次就AC了。