《编程之美》中的重建二叉树一题,文中所给方法自觉并非有“美”感。
我写了一个递归的方法。
1、每次递归只建立一个根节点,该根节点即为先序遍历的第一个字符,称为rootValue;
2、然后在中序遍历中找到rootValue,左边一段为左子树的中序遍历,右边一段为右子树的中序遍历;
3、根据中序遍历中rootValue的偏移量offset,可以在前序遍历找到左子树的前序遍历,和右子树的前序遍历;
如此,递归调用,即可完成。
#include <iostream>
#include <assert.h>
using namespace std;
struct NODE {
char value;
NODE *leftChild;
NODE *rightChild;
};
void preOrderTraverse (NODE *root){
if(root == NULL)
return;
cout << root->value;
preOrderTraverse(root->leftChild);
preOrderTraverse(root->rightChild);
}
void inOrderTraverse (NODE *root){
if(root == NULL)
return;
inOrderTraverse(root->leftChild);
cout << root->value;
inOrderTraverse(root->rightChild);
}
void postOrderTraverse (NODE *root){
if(root == NULL)
return;
postOrderTraverse(root->leftChild);
postOrderTraverse(root->rightChild);
cout << root->value;
}
int getOffset(char *pInOrder, char rootValue,
int begin, int end) {
for(int i = begin; i <= end; ++i) {
if(pInOrder[i] == rootValue){
return i - begin;
break;
}
}
}
NODE* build (char *pPreOrder, int preBegin, int preEnd,
char *pInOrder, int inBegin, int inEnd) {
NODE *root = new NODE;
root->value = pPreOrder[preBegin];
int rootOffset = getOffset(pInOrder, root->value, inBegin, inEnd);
if(rootOffset > 0){
root->leftChild = build(pPreOrder, preBegin + 1, preBegin + rootOffset,
pInOrder, inBegin, inBegin + rootOffset - 1);
}
else
root->leftChild = NULL;
if(rootOffset < inEnd - inBegin){
root->rightChild = build(pPreOrder, preBegin + rootOffset + 1, preEnd,
pInOrder, inBegin + rootOffset + 1, inEnd);
}
else
root->rightChild = NULL;
return root;
}
void Rebuild (char *pPreOrder, char *pInOrder,
int nTreeLength, NODE **pRoot){
if(pPreOrder == NULL)
cerr << "invalid input" << endl;
*pRoot = build(pPreOrder, 0, nTreeLength - 1, pInOrder, 0, nTreeLength - 1);
}
int main(){
char pPreOrder[] = "abcdefg";
char pInOrder[] = "bcaedgf";
NODE **pRoot = new NODE*;
*pRoot = NULL;
Rebuild(pPreOrder, pInOrder, 7, pRoot);
cout << "pre_order: ";
preOrderTraverse(*pRoot);
cout << "\nin_order: ";
inOrderTraverse(*pRoot);
cout << "\npost_order: ";
postOrderTraverse(*pRoot);
cout << endl;
return 0;
}