PTA 7-28 搜索树判断(镜像二叉搜索树的后序遍历)

Posted veeupup

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PTA 7-28 搜索树判断(镜像二叉搜索树的后序遍历)相关的知识,希望对你有一定的参考价值。

算法源代码在 Veeupup Github

考点:

  • 二叉搜索树遍历方式和性质运用

对于二叉搜索树,我们规定任一结点的左子树仅包含严格小于该结点的键值,而其右子树包含大于或等于该结点的键值。如果我们交换每个节点的左子树和右子树,得到的树叫做镜像二叉搜索树。

现在我们给出一个整数键值序列,请编写程序判断该序列是否为某棵二叉搜索树或某镜像二叉搜索树的前序遍历序列,如果是,则输出对应二叉树的后序遍历序列。

输入格式:

输入的第一行包含一个正整数N(≤1000),第二行包含N个整数,为给出的整数键值序列,数字间以空格分隔。

输出格式:

输出的第一行首先给出判断结果,如果输入的序列是某棵二叉搜索树或某镜像二叉搜索树的前序遍历序列,则输出YES,否侧输出NO。如果判断结果是YES,下一行输出对应二叉树的后序遍历序列。数字间以空格分隔,但行尾不能有多余的空格。

输入样例1:

7
8 6 5 7 10 8 11

输出样例1:

YES
5 7 6 8 11 10 8

输入样例2:

7
8 6 8 5 10 9 11

输出样例2:

NO

这道题想考二叉搜索树性质的运用以及二叉树的几种遍历方式,需要对二叉树的遍历方式和搜索二叉树的性质有比较好的理解,建议画图加深理解和推导。

思路:

对于给定的先序遍历序列,我们可以构建一颗二叉搜索树,然后根据生成的二叉搜索树的性质来做。

  1. 如果生成二叉搜索树的前序遍历序列和输入的序列的一致,那么直接输出后序遍历的值
  2. 如果不符合 1,那么需要和这棵树的镜像二叉搜索树的前序遍历进行比较,但我们此时不需要真的互换每个结点的左右结点,只需要在先序遍历时先访问右子结点,此时得到的序列就是镜像二叉树的序列
    当我们确定是镜像二叉树的序列的时候,我们就可以后序遍历,但此时后序遍历的顺序会有所区别,应该是先访问右子树,再访问左子树,最后访问本身结点的顺序来进行后序遍历,此时得到的就是镜像二叉树的后序遍历。

完整代码如下:

/* 
    Author: Veeupup
 */
#include <iostream>
#include <vector>
using namespace std;

const int maxn = 1010;

vector<int> inputOrder, preStr, preMirrorStr,postStr, postMirrorStr; // 保存输入的前序遍历的值,保存生成二叉搜索树的序列

struct node
{
    int data;
    node *left, *right;
    node(int _data): data(_data), left(NULL), right(NULL) {}
};

void insert(node* &root, int val) 
{
    if(root == NULL)
    {
        root = new node(val);
        return;
    }else if(val < root->data) {
        insert(root->left, val);
    }else {
        insert(root->right, val);
    }
}

// 后续遍历的值
void postOrder(node *root) {
    if(root == NULL)
        return;
    postOrder(root->left);
    postOrder(root->right);
    postStr.push_back(root->data);
}

void postMirrorOrder(node *root) {
    if(root == NULL)
        return;
    postMirrorOrder(root->right);
    postMirrorOrder(root->left);
    postMirrorStr.push_back(root->data);
}

void preOrder(node *root) {
    if(root == NULL)
        return;
    preStr.push_back(root->data);
    preOrder(root->left);
    preOrder(root->right);
}

void preMirrorOrder(node *root) {
    if(root == NULL)
        return;
    preMirrorStr.push_back(root->data);
    preMirrorOrder(root->right);
    preMirrorOrder(root->left);
}

int main()
{
    freopen("data.txt", "r", stdin);
    int n;
    scanf("%d", &n);
    int num;
    node *root = NULL;
    for (int i = 0; i < n; i++)
    {
        scanf("%d", &num);
        insert(root, num);
        inputOrder.push_back(num);  //保存
    }
    preOrder(root);
    preMirrorOrder(root);
    if (inputOrder == preStr)
    {
        printf("YES
");
        postOrder(root);
        for (int i = 0; i < postStr.size(); i++)
        {
            if(i > 0) {
                printf(" ");
            }
            printf("%d", postStr[i]);
        }
    }
    else if (inputOrder == preMirrorStr)
    {
        printf("YES
");
        postMirrorOrder(root);
        for (int i = 0; i < postMirrorStr.size(); i++)
        {
            if(i > 0) {
                printf(" ");
            }
            printf("%d", postMirrorStr[i]);
        }
    }
    else
    {
        printf("NO
");
    }

    return 0;
}

以上是关于PTA 7-28 搜索树判断(镜像二叉搜索树的后序遍历)的主要内容,如果未能解决你的问题,请参考以下文章

二叉搜索树的后序遍历判断

剑指OFFER 二叉搜索树的后序遍历

二叉搜索树的后序遍历

剑指——二叉搜索树的后序遍历

判断二叉搜索树的后序遍历序列

11 二叉搜索树的后序遍历序列