那么左右子树的前序和中序都有了,就可以递归了。下面提供了Java和C语言的实现:
class BinaryTreeNode{
int value;
BinaryTreeNode leftNode,rightNode;
}
public class Construct {
static BinaryTreeNode rebuild(int[] preorder,int[] inorder){
BinaryTreeNode root = rebuild(preorder,0,preorder.length-1,inorder,0,inorder.length-1);
return root;
}
//参数包含子遍历,以及遍历开始和结束的位置
static BinaryTreeNode rebuild(int[] preorder,int startPre,int endPre,int[] inorder,int startIn,int endIn){
if( startPre > endPre || startIn > endIn || preorder.length != inorder.length){
return null;
}
boolean haveRoot = false;
//前序第一个数为根节点
BinaryTreeNode root = new BinaryTreeNode();
for(int i=startIn;i<=endIn;i++){
//找根节点
if(inorder[i] == preorder[startPre]){
haveRoot = true;
root.value = preorder[startPre];
root.leftNode = rebuild(preorder, startPre+1, startPre+1+(i-startIn), inorder, startIn, i-1);
root.rightNode = rebuild(preorder, i-startIn+startPre+1, endPre, inorder, i+1, endIn);
//用数组索引比较复杂,另一种用复制数组的方法好理解。
//root.leftNode = rebuild(Arrays.copyOfRange(preorder, 1, i+1), Arrays.copyOfRange(inorder, 0, i));
//root.rightNode = rebuild(Arrays.copyOfRange(preorder, i+1, preorder.length), Arrays.copyOfRange(inorder, i+1,inorder.length));
}
}
if(!haveRoot){
System.out.println("没有找到根节点");
return null;
}
return root;
}
//后序遍历树
static void postorder(BinaryTreeNode root){
if(root == null){
System.out.println("根节点为空");
}
if(root.leftNode != null){
postorder(root.leftNode);
}
if(root.rightNode != null){
postorder(root.rightNode);
}
System.out.println(root.value);
}
public static void main(String[] args) {
int[] preorder = {1,2,4,7,3,5,6,8};
int[] inorder = {4,7,2,1,5,3,8,6};
postorder(rebuild(preorder, inorder));
}
}
#include
#include
typedef struct TreeNode{
int value;
TreeNode* left;
TreeNode* right;
}BiTree,*pTree;
TreeNode* constructCore(int* startpre,int* endpre,int* startin,int* endin){//参数为前序开始结束的位置,中序开始结束的位置
//前序第一个数是根节点的值
pTree root = (pTree)malloc(sizeof(BiTree));
root->value = startpre[0];
root->left = root->right = NULL;
if(startpre == endpre){
if(startin == endin && *startpre == *startin) return root;//重建完成
else printf("错误的输入");
}
//在中序中找根节点的值
int* rootInorder = startin;
while(rootInorder <= endin && *rootInorder != root->value) ++rootInorder;
if(rootInorder == endin && *rootInorder != root->value) printf("还是错误的输入");
int leftLen = rootInorder - startin;
int* leftEndpre = startpre + leftLen;
if(leftLen >0){
//构建左子树
root->left = constructCore(startpre +1,leftEndpre,startin,rootInorder -1);
}
if(leftLen < endpre-startpre){
//构建右子树,上述条件是左子树个数小于所有子树个数,所以必存在右子树
root->right = constructCore(leftEndpre +1,endpre,rootInorder +1,endin);
}
return root;
}
TreeNode* construct(int* preorder,int* inorder,int length){//数组作为参数时,传入的是地址。
if(preorder ==NULL || inorder == NULL || length<=0) return NULL;
return constructCore(preorder,preorder + length -1,inorder,inorder + length -1);
}
//后序输出
void postorder(pTree root){
if(root == NULL) printf("后序为空");
if(root->left != NULL) postorder(root->left);
if(root->right != NULL) postorder(root->right);
printf("%d",root->value);
printf("\n");
}
int main(){
pTree rootNode;
int a[] = {1,2,4,7,3,5,6,8};//前序
int b[] = {4,7,2,1,5,3,8,6};//中序
rootNode = construct(a,b,8);
postorder(rootNode);
return 0;
}