1. 程式人生 > 其它 ><資料結構>XDOJ332.二叉排序樹的判定

<資料結構>XDOJ332.二叉排序樹的判定

問題與解答

問題描述
給定一個二叉樹,判斷其是否是一個有效的二叉排序樹。
假設一個二叉排序樹具有如下特徵:
結點的左子樹只包含小於當前結點的樹。
結點的右子樹只包含大於當前結點的樹。
所有左子樹和右子樹自身必須也是二叉排序樹。
輸入格式
第一行兩個數n,root,分別表示二叉樹有n個結點,第root個結點是二叉樹的根。接下來共n行,第i行三個數val_i、left_i、right_i,分別表示第i個結點的值val是val_i,左兒子left是第left_i個結點,右兒子right是第right_i個結點。
節點0表示空。
1<=n<=100000,保證是合法的二叉樹
輸出格式
輸出"true"如果給定二叉樹是二叉排序樹,否則輸出"false"
樣例輸入


5 1
5 2 3
1 0 0
3 4 5
4 0 0
6 0 0
樣例輸出
false

#include<stdio.h>
#define MAXSIZE 1000001 //最大結點數
typedef struct {   //結構體表示結點
    int val;     //結點值
    int lchild;  //結點左子樹位置
    int rchild;  //結點右子樹位置
}Node;
Node data[MAXSIZE];  //結構體陣列表示樹
int Judge( Node data);  //遞迴方法,判斷是否為二叉排序樹

int main (void) {
    int n, root, i, j, val_i, left_i, right_i, flag;
    scanf ("%d %d", &n, &root);  //輸入結點數和根節點位置
    for (i = 1; i <= n; i++) {  //建立樹
        scanf ("%d %d %d", &val_i, &left_i, &right_i);
        data[i].val = val_i;
        data[i].lchild = left_i;
        data[i].rchild = right_i;
    }
    flag = Judge (data[root]);  //呼叫Judge函式
    if (flag) {
        printf ("true\n");
    }
    else {
        printf ("false\n");
    }
    return 0;
}

int Judge(Node p) {
    if (p.lchild == 0 && p.rchild == 0) return 1;  //終止條件,到達葉子結點
    
    //判斷當前結點是否滿足排序樹條件
    if (p.lchild != 0 && p.val <= data[p.lchild].val  //存在左子樹且結點值小於左子樹的值
        || p.rchild != 0 && p.val >= data[p.rchild].val) //存在右子樹且結點值大於右子樹的值
        return 0;  //若不滿足,返回0
    else { //若滿足:
       if(p.lchild != 0) return Judge(data[p.lchild]);  //遞迴判斷左子樹
       if(p.rchild != 0) return Judge(data[p.rchild]);  //遞迴判斷右子樹
    }
}

題後反思

  1. 在判斷當前結點與左右子樹的關係時,需要先確定左右子樹存在。即不能遺漏p.lchild != 0否則當前結點不存在左或右子樹時,還會繼續和data[0].val進行比較進而導致程式錯誤。
  2. Judge(data[p.lchild])前需要return