对给定的有N
个节点(N>=0
)的二叉树,给出中序遍历序列,并判断是否为二叉搜索树。
题目保证二叉树不超过200
个节点,节点数值在整型int
范围内且各不相同。
输入格式:
第一行是一个非负整数N
,表示有N
个节点
第二行是一个整数k
,是树根的元素值
接下来有N-1
行,每行是一个新节点,格式为r d e
三个整数,
r
表示该节点的父节点元素值(保证父节点存在);d
是方向,0
表示该节点为父节点的左儿子,1
表示右儿子;e
是该节点的元素值
输出格式:
首先输出二叉树的中序遍历序列,每个元素占一行。对于空树,不输出任何内容。
然后如果给定的树是二叉搜索树,输出Yes
否则输出No
输入样例:
对于图片中的二叉树:
3
20
20 0 10
20 1 25
输出样例:
10 20 25 Yes
代码如下:
#include <malloc.h> #include <stdio.h> #include <string.h> typedef struct BSTNode *BinTree; struct BSTNode { int data; BinTree left, right; }; int a[205]; int len = 0; BinTree create(); //创建空树 void InOrderTraversal (BinTree BT); //中序遍历 int main(){ int n; //结点数 int k; //树根的元素值 int flag = 0, flag1 = 0; scanf("%d", &n); if ( n==0 ){ printf("Yes\n"); return 0; } scanf("%d", &k); BinTree BT; BT = create(); BT->data = k; int i; for (i=0; i<n-1; i++){ //r表示该节点的父节点元素值(保证父节点存在); //d是方向,0表示该节点为父节点的左儿子,1表示右儿子; //e是该节点的元素值 int r, d, e; scanf("%d %d %d", &r, &d, &e); BinTree t = BT; if (r != t->data) { //搜索父结点 while (t->right){ t = t->right; if (r == t->data){ flag1 = 1; break; } } if (flag1 == 0) { t = BT; } while (t->left && flag1 == 0){ t = t->left; if (r == t->data){ break; } } } if ( d==0 ){ t->left = create(); t->left->data = e; } else if ( d==1 ){ t->right = create(); t->right->data = e; } } InOrderTraversal (BT); //打印中序遍历结果 for (i=1; i<len; i++){ if (a[i-1]>=a[i]){ flag = 1; break; } } if (flag == 0){ printf("Yes\n"); } else if (flag == 1){ printf("No\n"); } return 0; } BinTree create(){ //创建空树/结点? BinTree BT; BT = (BinTree)malloc(sizeof(struct BSTNode)); BT->left = BT->right = NULL; return BT; } void InOrderTraversal (BinTree BT){ //中序遍历 if (BT){ InOrderTraversal( BT->left ); a[len++] = BT->data; printf("%d\n", BT->data); InOrderTraversal( BT->right ); } }
其中:只有一个根结点也是二叉搜索树
二叉搜索树的中序遍历是从小到大输出的,可以利用这个特点来判断是否为二叉搜索树
搜索父结点的循环类似于暴力扫描,但是有缺陷,目前我找不出来,提交在PTA中测试点2未通过。原理:如果r不等于根节点的元素值,首先向右子树遍历,直到找到r等于结点元素值,修改flag1为1,跳出循环,如果右子树未找到,令t重新回到根结点,再往左子树遍历。
在此贴上PTA的测试点