L2-004 這是二叉搜索樹嗎? (25分)

題目描述:

一棵二叉搜索樹可被遞歸地定義爲具有下列性質的二叉樹:對於任一結點,

  • 其左子樹中所有結點的鍵值小於該結點的鍵值;
  • 其右子樹中所有結點的鍵值大於等於該結點的鍵值;
  • 其左右子樹都是二叉搜索樹。

所謂二叉搜索樹的“鏡像”,即將所有結點的左右子樹對換位置後所得到的樹。

給定一個整數鍵值序列,現請你編寫程序,判斷這是否是對一棵二叉搜索樹或其鏡像進行前序遍歷的結果。

輸入格式:

輸入的第一行給出正整數 N(≤1000)。隨後一行給出 N 個整數鍵值,其間以空格分隔。

輸出格式:

如果輸入序列是對一棵二叉搜索樹或其鏡像進行前序遍歷的結果,則首先在一行中輸出 YES ,然後在下一行輸出該樹後序遍歷的結果。數字間有 1 個空格,一行的首尾不得有多餘空格。若答案是否,則輸出 NO

輸入樣例 1:

7
8 6 5 7 10 8 11

輸出樣例 1:

YES
5 7 6 8 11 10 8

輸入樣例 2:

7
8 10 11 8 6 7 5

輸出樣例 2:

YES
11 8 10 7 5 6 8

輸入樣例 3:

7
8 6 8 5 10 9 11

輸出樣例 3:

NO
#include <iostream>
#include <algorithm>

using namespace std;

// 判斷前序
bool isPre(int *a, int left, int right){
    if (left >= right)
        return true;
    int i = left+1, j; // 根
    while (i<=right && a[i]<a[left]) // 左子樹小於根
        i++;
    j = i;
    while (i<=right && a[i]>=a[left]) // 右子樹大於等於根
        i++;
    if (i <= right)
        return false;
    bool m = isPre(a, left+1, j-1); // 遞歸左子樹
    bool n = isPre(a, j, right); // 遞歸右子樹
    return n&&m;
}

// 判斷鏡像
bool isMirror(int* a, int left, int right){
    if (left >= right)
        return true;
    int i = left+1, j;
    while (i<=right && a[i]>=a[left])
        i++;
    j = i;
    while (i<=right && a[i]<a[left])
        i++;
    if (i <= right)
        return false;
    bool m = isMirror(a, left+1, j-1);
    bool n = isMirror(a, j, right);
    return m&&n;
}

// 構造後序
void preInToPost(int len, int* pre, int* in, int* post){
    if (len <= 0)
        return ;
    int p, i;
    for (i = 0; i < len; i++)
        if (pre[0] == in[i]){
            p = i;
            break;
        }
    preInToPost(p, pre+1, in, post);
    preInToPost(len-p-1, pre+p+1, in+p+1, post+p);
    post[len-1] = pre[0];
}

// 鏡像構造後序
void preInToPost_Mirror(int len, int* pre, int* in, int* post){
    if (len <= 0)
        return ;
    int p, i;
    for (i = len-1; i >= 0; i--)
        if (pre[0] == in[i]){
            p = i;
            break;
        }
    preInToPost(p, pre+1, in, post);
    preInToPost(len-p-1, pre+p+1, in+p+1, post+p);
    post[len-1] = pre[0];
}

bool cmp(int a, int b){
    return a > b;
}

int pre[1005], in[1005], post[1005];

int main()
{
    int n;
    cin >> n;
    for (int i = 0; i < n; i++){
        cin >> pre[i];
        in[i] = pre[i];
    }
    
    if (isPre(pre, 0, n-1)){ // 二叉搜索樹
        cout << "YES" << endl;
        sort(in, in+n);
        preInToPost(n, pre, in, post);
        cout << post[0];
        for (int i = 1; i < n; i++)
            cout << " " << post[i];
    }
    else if (isMirror(pre, 0, n-1)){ // 鏡像
        cout << "YES" << endl;
        sort(in, in+n, cmp);
        preInToPost_Mirror(n, pre, in, post);
        cout << post[0];
        for (int i = 1; i < n; i++)
            cout << " " << post[i];
    } else
        cout << "NO";
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章