输入样例1:
9
38 45 42 24 58 30 67 12 51
输出样例1:
38 45 24 58 42 30 12 67 51
YES
输入样例2:
8
38 24 12 45 58 67 42 51
输出样例2:
38 45 24 58 42 12 67 51
NO
问题分析:三个步骤
1、根据输入数据插入结点建立二叉搜索树
2、对二叉搜索树进行层序遍历输出
3、判断树是否为完全二叉树
一、根据输入数据插入结点建立二叉搜索树
构造一个插入函数,对新来元素进行递归搜索并插入搜索树的动作。
递归边界:遍历到的结点为空,则在此处申请新空间,初始化结点插入搜索树
否则继续递归操作,根据结点元素数值大小判断向哪一边进行递归
二、对二叉搜索树进行层序遍历输出
定义两个指针pri和can[ ]
pri作为光标,表示当前在讨论的元素
can[ ]作为容器,按层序存储元素
can先存储第一个元素地址
光标按can中元素顺序进行遍历,can再对光标元素左右孩子依次存储,两者分别有序
最后c==p时即所有元素遍历完毕
三、判断是否为完全二叉树
当前遍历元素无非四种情况:
1、左孩子1右孩子1———>不用管它,继续遍历下一个
2、左孩子1右孩子NULL
3、左孩子NULL右孩子1 ——>一定不是完全二叉树
4、左孩子NULL右孩子NULL
2、4同样方法讨论,即判断接下来遍历的元素是否都为叶节点,不是则NO
AC代码:
#include <stdio.h>
#include <stdlib.h>
typedef struct TNode* Tree;
struct TNode{
int Data;
Tree Left,Right;
};
//需要插入建树,输出树,判断树
Tree insert(Tree BST,int x);
void out(Tree BST);
void judge(Tree BST);
Tree insert(Tree BST, int x){//递归,为空插入新节点
if(!BST){
BST=(Tree)malloc(sizeof(struct TNode));
BST->Data=x;
BST->Left=BST->Right=NULL;
}
if(x<BST->Data) BST->Right=insert(BST->Right,x);
else if(x>BST->Data) BST->Left=insert(BST->Left,x);
return BST;
}
void out(Tree BST){
Tree pri,can[20];
int p=0,c=0,i=0;
can[c++]=BST;
while(p!=c){
pri=can[p++];
if(!i++)printf("%d",pri->Data);
else printf(" %d",pri->Data);
if(pri->Left) can[c++]=pri->Left;
if(pri->Right) can[c++]=pri->Right;
}
}
void judge(Tree BST){
Tree x,can[20];//x表示当前扫描到的,can当作容器层序遍历
int p=0,c=0,q=0;
can[c++]=BST;
while(p!=c){
x=can[p++];
if(x->Left) can[c++]=x->Left;
if(x->Right) can[c++]=x->Right;
if(!x->Left&&x->Right){
printf("\nNO");
return;//当前扫描元素只要左空右非空直接结束
}
if((x->Left&&!x->Right)||(!x->Left&&!x->Right))q=1;
while(q==1&&p!=c){//直接嵌套循环遍历剩下所有元素,出现非叶节点则NO
x=can[p++];
if(x->Left||x->Right){
printf("\nNO");
return;
}
}
}
printf("\nYES");//包括第一种情况全部遍历依然没有NO的情况和2、4情况全部遍历剩余元素都为叶节点
}
int main()
{
int n,x;
Tree BST=NULL;//初始化要置为NULL,否则指向非系统分配的地址报错
if(scanf("%d",&n)){};
for(int i=0;i<n;i++){
if(scanf("%d",&x)){};
BST=insert(BST,x);
}
out(BST);
judge(BST);
return 0;
}
小白勿喷