剑指offer4:重建二叉树(后序遍历)

1. 题目描述

  输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。

2. 思路和方法

  (1)先序遍历序列的第一个元素必定是根节点,可以由此获取二叉树的根节点。

  (2)根据根节点,中序遍历序列中查找该节点,由中序遍历的性质可知,中序遍历中该根节点左边的序列必定在根节点的左子树中,根节点右边的序列必定在右子树中。由此可以知道先序遍历中左子树以及右子树的起止位置。

  (3)分别对左子树和右子树重复上述的过程,直至所有的子树的起止位置相等时,说明已经到达叶子节点,遍历完毕。

例子:

 

  前序遍历:1  2  4  5  7  8  3  6 (根左右)

  中序遍历:4  2  7  5  8  1  3  6(左根右)

  后序遍历:4  7  8  5  2  6  3  1(左右根)

  层次遍历:1  2  3  4  5  6  7  8 (共4层,与广度搜索一样,即广度遍历)

特殊例子:

前序遍历:1, 2, 4, 7, 3, 5, 6, 8 (根左右)

中序遍历:4, 7, 2, 1, 5, 3, 8, 6 (左根右)

后序遍历:7 4 2 5 8 6 3 1(左右根)

层次遍历:1 2 3 4 5 6 7 8 (共4层,与广度搜索一样,即广度遍历)

3. 核心代码

 1 /**
 2  * Definition for binary tree
 3  * struct TreeNode {
 4  *     int val;
 5  *     TreeNode *left;
 6  *     TreeNode *right;
 7  *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 8  * };
 9  */
10 class Solution {
11 public:
12     TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> vin) {
13         int len=vin.size();
14         if (len==0)
15             return NULL;
16         vector<int> left_pre,right_pre,left_vin,right_vin;
17         TreeNode* head = new TreeNode(pre[0]);
18         int gen = 0;
19         for(int i=0;i<len;i++)
20         {
21             if(vin[i]==pre[0])
22             {
23                 gen = i;
24                 break;
25             }
26         }
27         for(int i=0;i<gen;i++)
28         {
29             left_pre.push_back(pre[i+1]);
30             left_vin.push_back(vin[i]);
31         }
32         for(int i=gen+1;i<len;i++)
33         {
34             right_pre.push_back(pre[i]);
35             right_vin.push_back(vin[i]);
36         }
37         head->left = reConstructBinaryTree(left_pre,left_vin);
38         head->right = reConstructBinaryTree(right_pre,right_vin);
39         return head;
40     }
41 };
View Code

4. C++完整实现

  1 #include <iostream>  
  2 #include <deque>  
  3 using namespace std;
  4 
  5 //二叉树结点定义  
  6 typedef struct BiTreeNode{
  7     int data;
  8     //左右孩子指针  
  9     struct BiTreeNode *lchild;
 10     struct BiTreeNode *rchild;
 11 }BiTreeNode, *BiTree;
 12 
 13 //访问函数  
 14 void Visit(BiTree T)
 15 {
 16     if (T->data != -1)
 17         cout << T->data << " ";
 18 }
 19 
 20 //先序遍历  
 21 void PreOrder(BiTree T)
 22 {
 23     if (T != NULL)
 24     {
 25         //访问根节点  
 26         Visit(T);
 27         //访问左子结点  
 28         PreOrder(T->lchild);
 29         //访问右子结点  
 30         PreOrder(T->rchild);
 31     }
 32 }
 33 
 34 //中序遍历
 35 void InOrder(BiTree T)
 36 {
 37     if (T != NULL)
 38     {
 39         //访问左子结点
 40         InOrder(T->lchild);
 41         //访问根节点
 42         Visit(T);
 43         //访问右子结点
 44         InOrder(T->rchild);
 45     }
 46 }
 47 
 48 //后序遍历
 49 void PostOrder(BiTree T)
 50 {
 51     if (T != NULL)
 52     {
 53         //访问左子结点
 54         PostOrder(T->lchild);
 55         //访问右子结点
 56         PostOrder(T->rchild);
 57         //访问根节点
 58         Visit(T);
 59     }
 60 }
 61 
 62 BiTree constructor(int * startP, int * endP, int * startI, int * endI)
 63 {
 64     //前序遍历序列的第一个数字是根节点的值
 65     int rootValue = startP[0];
 66     BiTree root;
 67     root = (BiTree)malloc(sizeof(BiTreeNode));
 68     root->data = rootValue;
 69     root->lchild = root->rchild = NULL;
 70 
 71     if (startP == endP)
 72     {
 73         if (startI == endI && *startP == *startI)
 74             return root;
 75         else
 76             return NULL;
 77     }
 78 
 79     //在中序遍历中找到根节点的值
 80     int * rootI = startI;
 81     while (rootI <= endI && *rootI != rootValue)
 82         ++rootI;
 83 
 84     if (rootI == endI && *rootI != rootValue)
 85         return NULL;
 86 
 87     int leftlen = rootI - startI;
 88     int *leftPE = startP + leftlen;
 89     if (leftlen>0)
 90     {
 91         //构建左子树
 92         root->lchild = constructor(startP + 1, leftPE, startI, rootI - 1);
 93     }
 94     if (leftlen<endP - startP)
 95     {
 96         //构建右子树
 97         root->rchild = constructor(leftPE + 1, endP, rootI + 1, endI);
 98     }
 99 
100     return root;
101 }
102 
103 BiTree foo(int * pre, int * ino, int len)
104 {
105     if (pre == NULL || ino == NULL || len <= 0)
106         return NULL;
107 
108     return constructor(pre, pre + len - 1, ino, ino + len - 1);
109 }
110 
111 
112 int main()
113 {
114     //int pre[] = { 1, 2, 4, 5, 7, 8, 3, 6 };
115     //int ino[] = { 4, 2, 7, 5, 8, 1, 3, 6 };
116     int pre[] = { 1, 2, 4, 7, 3, 5, 6, 8 };
117     int ino[] = { 4, 7, 2, 1, 5, 3, 8, 6 };//7 4 2 5 8 6 3 1
118     int len = sizeof(pre) / sizeof(pre[0]);
119 
120     BiTree T = foo(pre, ino, len);
121 
122     cout << "二叉树根节点:";
123     cout << T->data << endl;
124 
125     cout << "先序遍历:";
126     PreOrder(T);
127     cout << endl;
128 
129     cout << "中序遍历:";
130     InOrder(T);
131     cout << endl;
132 
133     cout << "后序遍历:";
134     PostOrder(T);
135     cout << endl;
136     system("pause");
137     return 0;
138 }
View Code

参考资料

https://blog.csdn.net/My_Jobs/article/details/43451187

https://blog.csdn.net/wtyvhreal/article/details/45644843

猜你喜欢

转载自www.cnblogs.com/wxwhnu/p/11390471.html