已知二叉树的先序排列和中序排列,重构该二叉树,并输出该树的后序遍历
2018-03-13 19:39
453 查看
前言
好久没写算法题,第一次碰到居然懵了,心里想着用递归用递归,却怎么也想不出思路来。实现
思路举例:
前序遍历为:1 2 4 5 3 6 7
中序遍历为:4 2 5 1 6 3 7
我们可以由先序遍历的顺序得到二叉树中节点的顺序,如从1开始,这样在中序遍历中找到1的位置的时候,在1左边的即为1节点的左子树元素(4 2 5 ),在1右边的即为1节点的右子树元素(6 3 7),这是由中序遍历的定义所决定的。
然后我们再依据先序遍历,找到下一个节点2,再从中序遍历中找到2的位置,这样中序遍历中2的左子树元素有4, 2的右子树元素只有5(这里注意,我们在查找的时候只在1的左子树元素范围内查找,即4 2 5,中序遍历中除此之外的元素我们是不
4000
涉及的)。
依次往下重复…..
以上的部分就构成了我们的递归程序,那么作为递归所必须的递归出口该如何定义?
回想我们步骤中隐含的操作是遍历先序遍历,那么当给出的先序遍历数组遍历结束之后,我们的递归程序也应当结束,这可以算作一个递归出口,再有,我们在中序遍历中给左右子树元素划范围的时候,会涉及到左边界(left)以及右边界(right),其中隐含着的条件是左边界不能大于右边界(可以等于,表示只有一个元素)。
代码
/*!Copyright (c) 2017 Cheng Ligang . All rights reserved. * \author: Cheng Ligang * \mail: chengligang@buaa.edu.cn * \date: 2018/3/13 */ #include <stdio.h> const int max_nums = 100; //preOrder先序遍历数组,inOrder中序遍历数组 int preOrder[max_nums], inOrder[max_nums]; int nums = 0; //二叉树节点的定义 typedef struct BNode { int val; BNode * left_child; BNode * right_child; }BTree; //在中序遍历数组中返回对应先序遍历中item对应的位置值 int search(int item) { for (int i = 0; i < nums; i++) { if(item == inOrder[i]) return i; } return -1; } //创建给定val的新节点 BNode * createNode(int val) { BNode * node = new BNode; node->val = val; node->left_child = NULL; node->right_child = NULL; return node; } //给定当前指向先序遍历节点的下标以及该节点左右子树元素的在中序遍历中的范围(左、右边界) //返回重构好的二叉树 BTree * createTree(int &cur_pos, int left, int right) { //递归出口,遍历结束以及左边界小于右边界 if(cur_pos > nums -1 || left>right) return NULL; if(left == right) return createNode(preOrder[cur_pos]); int val = preOrder[cur_pos]; int pos = search(val); BNode * root = createNode(val); //递归调用自身,同时保证遍历指针指向先序遍历中的下一个元素。 cur_pos += 1; root->left_child = createTree(cur_pos, left, pos - 1); cur_pos += 1; root->right_child = createTree(cur_pos, pos + 1, right); //返回树的根节点 return root; } //递归实现后序遍历 void printPostOrder(BNode * root) { if(root == NULL) return ; printPostOrder(root->left_child); printPostOrder(root->right_child); printf("%d ", root->val); } int main() { scanf("%d", &nums);//输入元素个数 int i = 0; for(i = 0; i<nums; i++) scanf("%d", &preOrder[i]);//输入先序遍历 for(i = 0; i<nums; i++) scanf("%d", &inOrder[i]);//输入中序遍历 int cur_pos = 0;//当前指向先序遍历下标值 BTree * root = createTree(cur_pos, 0, nums - 1); printPostOrder(root);//后序遍历重构好的树 return 0; } //测试数据 //7 //1 2 4 5 3 6 7 //4 2 5 1 6 3 7
测试结果:
相关文章推荐
- 剑指offer——已知二叉树的先序和中序排列,重构二叉树
- 已知二叉树的先序遍历和中序遍历序列,输出后序遍历序列
- 已知中序和先序,求二叉树的重构问题
- 已知二叉树的先序遍历序列和中序遍历序列,输出该二叉树的后序遍历序列
- 已知二叉树的先序遍历序列和中序遍历序列,输出该二叉树的后序遍历序列
- 已知二叉树的前序遍历和中序遍历,求二叉树的后序遍历
- 二叉树系列(一):已知先序遍历序列和中序遍历序列,求后序遍历序列
- 通过前序遍历和中序遍历重建二叉树以及输出后序遍历(Java实现)(二)
- 已知二叉树的前序和中序遍历,重构该二叉树
- 3.9已知二叉树的 前序遍历和中序遍历的结果,重构出原二叉树
- 通过前序遍历和中序遍历重建二叉树以及输出后序遍历(Java实现)
- 二叉树由先序遍历和中序遍历输出后序遍历
- 二叉树系列(一):已知先序遍历序列和中序遍历序列,求后序遍历序列
- 已知一颗二叉树S的前序遍历和中序遍历 序列,请编程输出二叉树S的后续遍历序列.
- 【树】已知二叉树前序和中序遍历求后序遍历,及中序和后序遍历求前序遍历
- 已知先序和中序构建二叉树并且以层序输出
- 已知二叉树的前序和中序遍历,重构该二叉树
- 已知二叉树的先序遍历和中序遍历,如何求后序遍历
- 二叉树——已知二叉树先序,建树,并输出中序、后序,并求树叶数和深度
- 已知二叉树的先序遍历序列和中序遍历序列,输出该二叉树的后序遍历序列