(pat-a)1020. Tree Traversals (25)

原创 2017年03月09日 17:38:41

题目:题目链接,给出二叉树的后序、中序,求层序。

首先这里有个知识点,就是二叉树的搜索(遍历)分为几种:

  • 前序,pre order
  • 中序,in order
  • 后序,post order
  • 层次遍历,level order

其实前三种都属于二叉树的深搜(DFS),层次遍历就是广搜(BFS)。在这里要注意的是,如果想要唯一确定一棵二叉树,至少要给出“中序”;如果只知道前序、后序,是不能唯一确定一棵树的。

解题思路:根据给出的2个序列,建立起一棵二叉树。然后再对这棵树进行BFS。所以关键是建树的过程。

在这道题中,是根据后序和中序,去确立一颗树。其实算法的过程可以说是在模拟我们在纸上思考的过程。
根据PAT网站给出的测例,说明一下这个过程。
测例:

后序: 2 3 1 5 7 6 4
中序: 1 2 3 4 5 6 7

算法过程:

( 从整个序列开始)先看后序,最后一个是4,那么根结点就是4。然后在中序那里找到4,把中序分成3部分:123、4、567,分别对应左子树,根,右子树。然后根据子树的结点数(左子树有3个点,右子树有3个点),后序也相应地分成3部分:231、 576、 4:
这里写图片描述
然后对左子树子序列(“123”)和右子树的子序列(“567”)递归地进行上述过程,便构造出一棵树了。
如果看到这里还不是太明白,我们可以把该算法再走一会儿:

  • 我们先走左子树。中序为:123,后序为:231。同样,在后序中发现“1”是局部根结点,那么只剩下右子树“23”。如图:
    这里写图片描述

  • 中序的“23”对应后序的“23”,那么“3”就是局部根结点,“2”就是其左结点了:(这里的左子树只剩下一个结点,整棵树的左边的递归终止)
    这里写图片描述

  • 剩下就是整棵树的右边“567”了,相信大家已经会自己演绎了,那剩下的就是代码的事情了。

代码:(代码粗糙,不过我会以注释的形式去说明一些关键的部分):

#include <iostream>
#include <queue>
#include <vector>
using namespace std;

/* 二叉树的结点 */
struct Node {
    int element;
    Node* left;
    Node* right;

    Node() {
        element = -1;
        left = right = NULL;
    }

    Node(int e, Node* l = NULL, Node* r = NULL) {
        this->element = e;
        this->left = l;
        this->right = r;
    }
};

/* 二叉树。在Node层上再抽象出BTree一层是为了方便操作 */
class BTree {
public:
    BTree() {
        root = NULL;
    }

    BTree(Node* node) {
        root = node;
    }

    ~BTree() {
        clear(root);
    }

    vector<int> bfs() const {
        Node* tmp = root;
        vector<int> resultList;
        queue<Node*> Q;
        Q.push(tmp);
        while (!Q.empty()) {
            Node* curNode = Q.front();
            Q.pop();

            // current
            resultList.push_back(curNode->element);

            // next
            if (curNode->left != NULL) {
                Q.push(curNode->left);
            }
            if (curNode->right != NULL) {
                Q.push(curNode->right);
            }
        }
        return resultList;
    }

private:
    Node* root; // 存储根结点

    /* 注意,释放一棵树的堆内存,需要采取后序的方式 */
    void clear(Node* root) {
        if (root == NULL) return;
        clear(root->left);
        clear(root->right);
        delete root;
    }
};

const int CASE_NUM = 1;
const int MAX_NODE_NUM = 30;
int nodenum;
int postOrder[MAX_NODE_NUM], inOrder[MAX_NODE_NUM];

/* 递归地 建立起一棵二叉树 */
Node* buildTree(int postLeft, int postRight, int inLeft, int inRight) {
    if (inRight <= inLeft || postRight <= postLeft) return NULL; // 递归的终止条件

    int rootElement = postOrder[postRight - 1]; // 后序子序列中最后一个就是根结点
    Node* ret = new Node(rootElement); // 分配内存,建立根结点
    int pos;
    // 然后在中序子序列中定位根结点的位置
    for (int i = inLeft; i < inRight; ++i) {
        if (rootElement == inOrder[i]) {
            pos = i; // pos就是根结点的位置
            break;
        }
    }
    // 因为在中序中,根结点一旦确定,那么它左边的序列就是左子树,右边的序列就是右子树
    int leftCount = pos - inLeft; // 左边序列的长度
    int rightCount = inRight - pos; // 右边序列的长度

    ret->left = buildTree(postLeft, postLeft + leftCount, inLeft, pos); // 递归:对左子树再进行建树的过程
    ret->right = buildTree(postLeft + leftCount, postRight - 1, pos + 1, inRight); // 递归:对右子树进行建树

    return ret; // 返回当前根结点(局部根结点)
}


int main() {
    int casenum = CASE_NUM;
    while (casenum--) {

        // 处理输入
        cin >> nodenum;
        for (int i = 0; i < nodenum; ++i) {
            cin >> postOrder[i];
        }
        for (int i = 0; i < nodenum; ++i) {
            cin >> inOrder[i];
        }

        // 建树
        Node* root = buildTree(0, nodenum, 0, nodenum);
        BTree* bTree = new BTree(root);

        // 按照格式输出结果
        vector<int> levelOrder = bTree->bfs();
        for (int i = 0, len = levelOrder.size(); i < len; ++i) {
            cout << levelOrder[i];
            if (i == len - 1) {
                cout << endl;
            } else {
                cout << ' ';
            }
        }

        delete bTree; // 记得释放堆内存哦!
    }

    return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。

PAT A1020. Tree Traversals (25)

Suppose that all the keys in a binary tree are distinct positive integers. Given the postorder and i...
  • jolivan
  • jolivan
  • 2017年02月24日 01:34
  • 82

1020. Tree Traversals (25)-PAT甲级真题

1020. Tree Traversals (25) Suppose that all the keys in a binary tree are distinct positive int...
  • liuchuo
  • liuchuo
  • 2016年08月06日 18:31
  • 331

PAT (Advanced Level) Practise 1020. Tree Traversals (25)

题意:给你一个二叉树的后序和中序遍历的序列,输出前序遍历的序列. 二叉树遍历第一题,当做模板留个纪念吧......

PAT: 1020. Tree Traversals (25)

PAT Tree Traversals 二叉树遍历 由中序和后序构建唯一二叉树
  • ZJFCLH
  • ZJFCLH
  • 2014年03月17日 22:33
  • 856

PAT A 1020.Tree Traversals (25)

题目

PAT 1020. Tree Traversals (25)

1020. Tree Traversals (25) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 16000 ...

PAT - 甲级 - 1020. Tree Traversals (25)(层次遍历)

题目描述: Suppose that all the keys in a binary tree are distinct positive integers. Given the postorde...

PAT (Advanced Level) Practise 1020 Tree Traversals (25)

1020. Tree Traversals (25) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 16000 ...

[PAT]1020. Tree Traversals (25)

/************************************************************** 1020. Tree Traversals (25) 时间限制 400...
  • fnzsjt
  • fnzsjt
  • 2014年11月23日 11:11
  • 614

pat1020Tree Traversals (25)

题意分析: (1)这是很数据结构中很经典的一类题型,给出中序序列和先序或者后序序列中的一种,求另外另类序列。一般若是求层序,需要构建二叉树,如果不是,可以不用建树; (2)建树的过程是一个递归的过程,...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:(pat-a)1020. Tree Traversals (25)
举报原因:
原因补充:

(最多只允许输入30个字)