编程之美-3.9-重建二叉树
1. 简述
给定一棵二叉树,假定每个节点都用唯一的字符表示,具体结构如下:
struct NODE {
NODE* pLeft;
NODE* pRight;
char chValue;
};
NODE* pLeft;
NODE* pRight;
char chValue;
};
假设已经有了前序遍历和中序遍历结果,希望通过一个算法重建这棵树。
给定函数的定义如下:
void Rebuild(char* pPreOrder, char* pInOrder, int nTreeLen, NODE** pRoot);
参数
pPreOrder:前序遍历结果的字符串数组。
pInOrder: 中序遍历结果的字符串数组。
nTreeLen: 树的长度。
pRoot: 根据前序和中序遍历结果重新构建树的根节点。
例如
前序遍历结果:a b d c e f
中序遍历结果:d b a e c f
2. 思路
递归解决相对容易些。
递归结束条件是长度小于1,此时令*pRoot=NULL即可。
递归主体中,在中序遍历结果中找前序结果的第一个字符,找到后记录其下标为index,如果找不到说明前序遍历和中序遍历有问题,说明错误信息,然后直接返回。找到index后,新建一个节点,让*pRoot指向它,其数值为前序的第一个字符,然后递归求*pRoot的左孩子和右孩子。
递归左孩子:Rebuild( pPreOrder+1,pInOrder, index, &((*pRoot)->pLeft) )
递归右孩子:Rebuild( pPreOrder+index+1, pInOrder+index+1, nTreeLen-index-1, &((*pRoot)->pRight) )
3. 代码
#include <iostream>
#include <stack>
using namespace std;
struct NODE {
NODE* pLeft;
NODE* pRight;
char chValue;
};
void Rebuild(char* pPreOrder, char* pInOrder, int nTreeLen, NODE** pRoot) {
if(nTreeLen <= 0) { // 递归结束
*pRoot = NULL;
return;
}
else { // 递归主体
int index = 0;
while(index < nTreeLen && pPreOrder[0]!=pInOrder[index])
index++;
if(index>=nTreeLen) {
cout << "前序和中序字符串不匹配,有问题" << endl;
cout << "在中序字符串中,找不到:" << pPreOrder[0] << endl;
return;
}
else {
*pRoot = new NODE;
(*pRoot)->chValue = pPreOrder[0];
Rebuild(pPreOrder+1, pInOrder, index, &((*pRoot)->pLeft));
Rebuild(pPreOrder+index+1, pInOrder+index+1, nTreeLen-index-1, &((*pRoot)->pRight) );
}
}
}
void PrintTree(const NODE* root) { // 先根序遍历
stack<const NODE*> store;
store.push(root);
while(!store.empty()) {
// output root
cout << store.top()->chValue << ":\t";
// output left
if(store.top()->pLeft == NULL)
cout << "NULL";
else
cout << store.top()->pLeft->chValue;
cout << " , ";
// output right
if(store.top()->pRight == NULL)
cout << "NULL";
else
cout << store.top()->pRight->chValue;
cout << endl;
// push right
const NODE* tmp = store.top();
store.pop();
if(tmp->pRight)
store.push(tmp->pRight);
if(tmp->pLeft)
store.push(tmp->pLeft);
}
}
int main() {
char* pPreOrder = "abdcef";
char* pInOrder = "dbaecf";
NODE* pRoot;
Rebuild(pPreOrder, pInOrder, strlen(pPreOrder), &pRoot);
PrintTree(pRoot);
system("PAUSE");
return 0;
}
#include <stack>
using namespace std;
struct NODE {
NODE* pLeft;
NODE* pRight;
char chValue;
};
void Rebuild(char* pPreOrder, char* pInOrder, int nTreeLen, NODE** pRoot) {
if(nTreeLen <= 0) { // 递归结束
*pRoot = NULL;
return;
}
else { // 递归主体
int index = 0;
while(index < nTreeLen && pPreOrder[0]!=pInOrder[index])
index++;
if(index>=nTreeLen) {
cout << "前序和中序字符串不匹配,有问题" << endl;
cout << "在中序字符串中,找不到:" << pPreOrder[0] << endl;
return;
}
else {
*pRoot = new NODE;
(*pRoot)->chValue = pPreOrder[0];
Rebuild(pPreOrder+1, pInOrder, index, &((*pRoot)->pLeft));
Rebuild(pPreOrder+index+1, pInOrder+index+1, nTreeLen-index-1, &((*pRoot)->pRight) );
}
}
}
void PrintTree(const NODE* root) { // 先根序遍历
stack<const NODE*> store;
store.push(root);
while(!store.empty()) {
// output root
cout << store.top()->chValue << ":\t";
// output left
if(store.top()->pLeft == NULL)
cout << "NULL";
else
cout << store.top()->pLeft->chValue;
cout << " , ";
// output right
if(store.top()->pRight == NULL)
cout << "NULL";
else
cout << store.top()->pRight->chValue;
cout << endl;
// push right
const NODE* tmp = store.top();
store.pop();
if(tmp->pRight)
store.push(tmp->pRight);
if(tmp->pLeft)
store.push(tmp->pLeft);
}
}
int main() {
char* pPreOrder = "abdcef";
char* pInOrder = "dbaecf";
NODE* pRoot;
Rebuild(pPreOrder, pInOrder, strlen(pPreOrder), &pRoot);
PrintTree(pRoot);
system("PAUSE");
return 0;
}
输出结果为:
4. 参考
编程之美,3.9节,重建二叉树