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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Deosiree

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值