7-22 搜索树判断 (25分)(C语言实现)
对于二叉搜索树,我们规定任一结点的左子树仅包含严格小于该结点的键值,而其右子树包含大于或等于该结点的键值。如果我们交换每个节点的左子树和右子树,得到的树叫做镜像二叉搜索树。
现在我们给出一个整数键值序列,请编写程序判断该序列是否为某棵二叉搜索树或某镜像二叉搜索树的前序遍历序列,如果是,则输出对应二叉树的后序遍历序列。
输入格式:
输入的第一行包含一个正整数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
C语言实现
#include<stdio.h>
#include<stdlib.h>
typedef struct node *tree;
struct node{
int data;
int flag;
tree left;
tree right;
};
int ttp=0,tp=0,fg=1;
tree reTree(tree t,int m);
void myprint(tree t);
tree reteemirror(tree t,int m);
int main(){
int n,m;
tree tr=NULL,trm=NULL;
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d",&m);
tr=reTree(tr,m);
trm=reteemirror(trm,m);
}
if(ttp==0){//判断搜索树
printf("YES\n");
myprint(tr);
}else if(tp==0){//判断镜子树
printf("YES\n");
myprint(trm);
}else printf("NO\n");
return 0;
}
//打印后序函数
void myprint(tree t){
if(t!=NULL){
myprint(t->left);
myprint(t->right);
if(fg==1){
printf("%d",t->data);
fg++;
}else printf(" %d",t->data);
}
}
//还原镜子树
tree reteemirror(tree t,int m){
if(t==NULL){
t=(tree)malloc(sizeof(struct node));
t->left=NULL;
t->right=NULL;
t->data=m;
t->flag=0;
return t;
}
if(t->data <= m && t->flag==0){
t->left=reteemirror(t->left,m);
}else{//一旦有了右树枝,就不能在向左树枝插入了,所以有一个flag进行判断
if(t->data <= m)tp=1;//如果插入的m不符合搜索树的规则就标记
t->flag=1;
t->right=reteemirror(t->right,m);
}
return t;
}
//还原搜索树
tree reTree(tree t,int m){
if(t==NULL){
t=(tree)malloc(sizeof(struct node));
t->left=NULL;
t->right=NULL;
t->data=m;
t->flag=0;
return t;
}
if(t->data > m && t->flag==0){
t->left=reTree(t->left,m);
}else{//一旦有了右树枝,就不能在向左树枝插入了,所以有一个flag进行判断
if(t->data > m)ttp=1;//如果插入的m不符合二叉树的规则就标记
t->flag=1;
t->right=reTree(t->right,m);
}
return t;
}
主要思想
这个题主要是对给出搜索树的前序,进行还原树。这个题我主要是对结点进行了:一旦它开始插入右孩子,就再也不对该结点插入左孩子了。所以我用了一个flag经行了标记,标记了的不能插入左孩子,只能插入右孩子。
至于镜子树就更好写了就不多说了。