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 };
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 }