• 7、(★、※)判断一个序列是否是二叉查找树的后序、前序遍历序列


     转载https://blog.csdn.net/attitudeisaltitude/article/details/9835785

    一、题目:输入一个整数数组,判断该数组是不是某二元查找树的后序遍历的结果。如果是返回true,否则返回false。

    思路在后续遍历得到的序列中,最后一个元素为树的根结点。从头开始扫描这个序列,比根结点小的元素都应该位于序列的左半部分;从第一个大于根结点开始到根结点前面的一个元素为止,所有元素都应该大于根结点,因为这部分元素对应的是树的右子树。根据这样的划分,把序列划分为左右两部分,我们递归地确认序列的左、右两部分是不是都是二元查找树。

    例如以序列{5、7、6、9、11、10、8}为例,后序遍历结果的最后一个数字8就是根节点的值。在这个数组中,前3个数字5、7和6都比8小,是值为8的节点的左子树节点;后3个数字9,11,10都比8大,是值为8的节点的右子树节点。 我们接下来用同样的方法确定与数组每一部分对应的子树的结构。这其实就是一个递归的过程。对于序列5,7,6,最后一个数字6是左子树的根节点的值。数字5比6小,是值为6的节点的左子结点,而7则是它的右子节点。同样,在序列9,11,10中,最后一个数字10是右子树的根节点,数字9比10小,是值为10的节点的左子结点,而11则是它的右子结点。

    再分析另一个序列{7,4,6,5}。后序遍历的最后一个数是根节点,因此根节点的值是5.由于第一个数字7大于5,因此在对应的二叉搜索树中,根节点上是没有左子树的,数字7,4,6都是右子树节点的值。但我们发现在右子树中有一个节点的值是4,比根节点的值5小,这违背了二叉搜索树的定义。因此不存在一颗二叉搜索树。

    代码:

    #include <iostream>
    #include <vector>
    #include <cstdio>
    
    using namespace std;
    
    struct Node {
        int data;
        Node *lchild, *rchild;
    };
    
    vector<int> post;
    
    //检查序列post是否是二叉查找树的后序遍历序列,st与ed分别是序列的开始与结束位置
    Node* Create(bool& flag, int st, int ed) {
    
        if (st > ed) return NULL;
    
    
        Node* root = new Node;
        root->data = post[ed];
    
        int k;
        for (k=st; k < ed; k++) {
            if (post[k] > post[ed]) {
                break;
            }
        }
        for (int i = k; i < ed; i++) {
            if (post[i] < post[ed]) {
                flag = false;
                //return NULL;
            }
                
        }
        root->lchild = Create(flag, st, k - 1);
        root->rchild = Create(flag, k, ed - 1);
        return root;
    
    }
    
    void preTraverse(Node* root) {
        if (root == NULL) return;
        printf("%d ", root->data);
        preTraverse(root->lchild);
        preTraverse(root->rchild);
    }
    
    void inTraverse(Node* root) {
        if (root == NULL) return;
        inTraverse(root->lchild);
        printf("%d ", root->data);
        inTraverse(root->rchild);
    
    }
    
    void postTraverse(Node* root) {
        if (root == NULL) return;
        postTraverse(root->lchild);
        postTraverse(root->rchild);
        printf("%d ", root->data);
    }
    
    
    int main(){
    
        int n;
        scanf("%d", &n);
        post.resize(n);
        for (int i = 0; i < n; i++) {
            scanf("%d", &post[i]);
        }
        bool flag = true;
        Node* root = Create(flag, 0, n - 1);
    
        if (flag) {
            printf("YES");
            printf("
    前序遍历
    ");
            preTraverse(root);
            printf("
    中序遍历
    ");
            inTraverse(root);
            printf("
    后序遍历
    ");
            postTraverse(root);
        }
        else {
            printf("NO
    ");
        }
    
        return 0;
    }

     二、题目:输入一个整数数组,判断该数组是不是某二元查找树的前序遍历的结果。如果是返回true,否则返回false。

    思路同理,在前续遍历得到的序列中,第一个元素为树的根结点。从第二个节点开始扫描这个序列,比根结点小的元素都应该位于序列的左半部分;从第一个大于根结点开始到最后一个元素为止,所有元素都应该大于跟结点,因为这部分元素对应的是树的右子树。根据这样的划分,把序列划分为左右两部分,我们递归地确认序列的左、右两部分是不是都是二元查找树。

    代码:

    //检查序列pre是否是二叉查找树的前序遍历序列,st与ed分别是序列的开始与结束位置
    Node* Create(bool& flag, int st, int ed) {
    
        if (st > ed) return NULL;
    
        Node* root = new Node;
        root->data = pre[st];
    
        int k;
        for (k=st+1; k <= ed; k++) {
            if (pre[k] > pre[st]) {
                break;
            }
        }
        for (int i = k; i <= ed; i++) {
            if (pre[i] < pre[st]) {
                flag = false;
                //return NULL;
            }
                
        }
        root->lchild = Create(flag, st + 1, k - 1);
        root->rchild = Create(flag, k, ed);
        return root;
    
    }
  • 相关阅读:
    第11条:用zip函数同时遍历两个迭代器
    第10条:尽量用enumerate取代range
    第9条:用生成器表达式来改写数据量较大的列表推导式
    MySQL的约束
    VMware下所有的系统网卡启动不起来
    windows下的mysql闪退问题
    大型网站架构模式
    MySQL的information_schema库
    mysql复制表结构和内容
    希尔排序 堆排序 归并排序
  • 原文地址:https://www.cnblogs.com/fuqia/p/9548316.html
Copyright © 2020-2023  润新知