說幹就幹,先上一篇昨天寫的文章。
以一道題目來說明如何建立二叉樹。
題目:已知先序遍曆,中序遍曆 建立二叉樹,然後求後序遍曆。
e.g. 先序:a b d e i j c f g
中序:d b i e j a f c g
後序:d i j e b f g c a //期望結果
解法:先序中的首元素a 必為該二叉樹的根結點,在中序序列裡a之前的元素一定是a的左子樹部分,a之後的元素一定為a的右子樹部分。
所以,可以看作,先序: root | 左子樹 | 右子樹
中序: 左子樹 | root | 右子樹
由此, 我們可以遞迴的得到該二叉樹。 即,先得到root根結點,然後,對左子樹進行同樣的操作,然後對右子樹進行同樣的操作。
所以建立二叉樹的過程可看作:
MakeBinaryTree(...)
{
得到root 根結點
MakeBinaryTree( 左子樹 );
MakeBinaryTree( 右子樹 );
}
代碼實現:C++語言: 貼彩色代碼可用:http://fayaa.com/code/new/
#include <iostream>
using namespace std;
typedef struct BinaryTreeNode
{
char data;
BinaryTreeNode * leftChild;
BinaryTreeNode * rightChild;
}Node;
void MakeBinaryTree(Node** root, char* preOrder, char* midOrder, int length)
{
if (length == 0)
{
(*root) = NULL;
return;
}
(*root) = new Node;
(*root)->data = *preOrder;
char * rootplace = strchr(midOrder, (*root)->data);
if (rootplace == NULL)
{
cout <<"input wrong order sample!"<<endl;
}
int leftTreeLength = strlen(midOrder) - strlen(rootplace);
int rightTreeLength = length - leftTreeLength - 1;
MakeBinaryTree(&(*root)->leftChild, preOrder+1, midOrder, leftTreeLength);
MakeBinaryTree(&(*root)->rightChild, preOrder+leftTreeLength+1, rootplace+1, rightTreeLength);
}
void PostTraverse(Node* root)
{
if (root == NULL)
return;
PostTraverse(root->leftChild);
PostTraverse(root->rightChild);
cout << root->data;
}
int main(int argc, const char** argv)
{
char pre[] = "abdeijcfg";
char mid[] = "dbiejafcg";
Node* r;
MakeBinaryTree(&r, pre, mid, strlen(pre));
PostTraverse(r);
return 0;
}
題外話,
1 如果已知中序,後序遍曆結果,求先序。由於後序可看作 左子樹 | 右子樹 | 根,可以考慮從後向前操作,這樣可以先確定根。
2 如何刪除樹呢?
3 如何非遞迴實現呢?