對給定的有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的測試點