BST二叉查找樹的性質

性質

對二叉查找樹進行中序遍歷,遍歷的結果是有序的。

題目1:Is It a Binary Search Tree

https://pintia.cn/problem-sets/994805342720868352/problems/994805440976633856

自己寫的(多點的,建兩棵樹)

省題

  輸入先序數組,按照先序數組建BST樹/BST鏡像樹。
  若該數組確實是BST樹/BST鏡像樹的先序數組,那麼輸出YES,再輸出相對應(BST樹/BST鏡像樹)樹的後序數組

  1. 這裏BST的定義標準
    a)The left subtree of a node contains only nodes with keys less than the node’s key.
    b)The right subtree of a node contains only nodes with keys greater than or equal to the node’s key.
    c)Both the left and right subtrees must also be binary search trees
    小於根節點的在左子樹沒變;但是右子樹的性質變爲了大於等於根節點
  2. 鏡像BST樹的定義
    If we swap the left and right subtrees of every node, then the resulting tree is called the Mirror Image of a BST.
    如果我們交換每個節點的左右子樹,那麼得到的樹就稱爲BST的鏡像。
    .

思路

設bool flag=false,若有 爲BST/鏡像BST的先序數組 其中一條滿足則爲true
根據先序數組建樹,若爲BST的先序數組,flag=true
若flag=false,再根據先序數組建鏡像樹,若爲鏡像BST的先序數組,flag=true
若flag=true則YES,按後序遍歷輸出,否則NO

  根據鏡像BST的定義可知,鏡像BST左右孩子的定義與BST正相反,即
          大於等於根節點的在左子樹;小於根節點的在右子樹
按照建樹的函數及其過程如法炮製建鏡像樹的函數及其過程

AC代碼

//根據先序建BST(第一個元素爲根),判斷該BST的先序是否爲輸入的先序
//如果是的,就輸出後序
#include<bits/stdc++.h>
using namespace std;
const int maxv=1010;
struct node{
    int data;
    node* lchild;
    node* rchild;
};
int n,pre[maxv],step;
//新建結點
node* newnode(int x)
{
    node* root=new node;
    root->data=x;
    root->lchild=root->rchild=NULL;
    return root;
}
//插入
void insert(node* &root,int x)
{
    if(root==NULL){
        root=newnode(x);
        return;
    }
    //省題
    /*The left subtree of a node contains only nodes with keys less than the node's key.
The right subtree of a node contains only nodes with keys greater than or equal to the node's key.*/
    else if(x<root->data)//小於根節點,在其左子樹
        insert(root->lchild,x);
    else if(x>=root->data)
        insert(root->rchild,x);
}
//鏡像插入
void Minsert(node* &root,int x)
{
    if(root==NULL){
        root=newnode(x);
        return;
    }
    //省題
    /*If we swap the left and right subtrees of every node, then the resulting tree is called the Mirror Image of a BST.*/
    else if(x>=root->data)//大於等於根節點,在其左子樹(和原來的相反)
        Minsert(root->lchild,x);
    else if(x<root->data)
        Minsert(root->rchild,x);
}
//建樹
node* create()
{
    node* root=NULL;
    for(int i=1;i<=n;i++)
        insert(root,pre[i]);
    return root;
}
//鏡像建樹
node* Mcreate()
{
    node* root=NULL;
    for(int i=1;i<=n;i++)
        Minsert(root,pre[i]);
    return root;
}
bool preDFS(int &step,node* root)
{
    if(pre[step]!=root->data)
        return false;
    if(root->lchild!=NULL)
        if(!preDFS(++step,root->lchild))
            return false;
    if(root->rchild!=NULL)
        if(!preDFS(++step,root->rchild))
            return false;
    return true;
}
void postDFS(node* root,node *R)
{
    if(root->lchild!=NULL)
        postDFS(root->lchild,R);
    if(root->rchild!=NULL)
        postDFS(root->rchild,R);
    printf("%d%s",root->data,root==R?"\n":" ");
}

int main(){
    while(scanf("%d",&n)!=EOF){
        bool flag=false;
        for(int i=1;i<=n;i++)
            scanf("%d",&pre[i]);
        node* root=create();
        step=1;
        if(preDFS(step,root))
            flag=true;
        if(!flag){
            step=1;
            root=Mcreate();
            if(preDFS(step,root))
                flag=true;
        }
        if(flag){
            printf("YES\n");
            postDFS(root,root);
        }
        else
            printf("NO\n");
    }
    return 0;
}

小藍書上的(單點的,根據BST寫兩種的先序序列)

不同於我自己寫的:建兩棵樹分別判斷
小藍書上寫的是:建一棵樹,根據這棵樹遍歷出BST/鏡像BST的先序序列

根據BST遍歷出鏡像BST的先序序列就是把左右根的遍歷順序交換爲右左根,來滿足鏡像BST和BST的左右孩子相反的定義

AC代碼

#include<bits/stdc++.h>
using namespace std;
struct node {
    int data;           //數據域
    node *left,*right;  //指針域
} ;
void insert(node* &root, int data) {
    if (root == NULL) {//到達空結點時, 即爲需要插入的位置
        root = new node;
        root->data = data;
        root->left = root->right = NULL;//此句不能漏
        return;
    }
    if (data < root->data)//插在左子樹
        insert (root->left, data);
    else//插在右子樹
        insert(root->right, data);
}
//先序遍歷, 結果存在vi
void preOrder(node* root, vector<int>&vi) {
    if(root == NULL)
        return;
    vi.push_back(root->data);
    preOrder(root->left,vi);
    preOrder(root->right,vi);
}
//鏡像樹先序遍歷, 結果存放於vi
void preOrderMirror(node* root, vector<int>&vi) {
    if(root == NULL)
        return;
    vi.push_back(root->data);
    preOrderMirror(root->right, vi);
    preOrderMirror(root->left, vi);
}
//後序遍歷, 結果存放於vi
void postOrder(node* root,vector<int>&vi) {
    if(root == NULL)
        return;
    postOrder(root->left, vi);
    postOrder(root->right, vi);
    vi.push_back(root->data);
}
//鏡像樹後序遍歷, 結果存放於vi
void postOrderMirror(node* root, vector<int>&vi) {
    if(root == NULL)
        return;
    postOrderMirror(root->right, vi);
    postOrderMirror(root->left, vi);
    vi.push_back(root->data);
}
//origin 存放初始序列
//pre、post 爲先序、後序, preM、postM 爲鏡像樹先序、後序
vector<int> origin, pre, preM, post, postM;
int main() {
    int n, data;
    node* root=NULL;//定義頭結點
    scanf ("%d", &n);//輸入結點個數
    for(int i = 0; i < n; i++) {
        scanf("%d", &data);
        origin.push_back(data);//將數據加入origin
        insert(root, data);//將data 插入二叉樹
    }
    preOrder(root, pre);            //求先序
    preOrderMirror(root, preM);     //求鏡像樹先序
    postOrder(root, post);          //求後序
    postOrderMirror (root, postM);  //求鏡像樹後序
    if (origin == pre) {        //初始序列等於先序序列
        printf("YES\n");
        for (int i = 0; i < post.size(); i++) {
            printf ("%d", post[i]);
            if(i < post.size() -1)
                printf(" ");
        }
    } else if(origin == preM) { //初始序列等於鏡像樹先序序列
        printf("YES\n");
        for (int i = 0; i < postM. size(); i++) {
            printf("%d", postM[i]);
            if(i <postM.size() -1)
                printf(" ");
        }
    } else {
        printf("NO\n"); //否則輸出NO
    }
    return 0;
}

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