1. 程式人生 > >據前序遍歷和中序遍歷重建二叉樹

據前序遍歷和中序遍歷重建二叉樹

這是一道面試題

由前序遍歷和中序遍歷重建二叉樹(前序序列:1 2 3 4 5 6 - 中序序列:3 2 4 1 6 5)資料不含重複值

這個可以分析一下

前序遍歷序列1 2 3 4 5 6,前序遍歷規則是根--左--右

中序遍歷序列3 2 4 1 6 5,中序遍歷規則是左--根--右

由前序遍歷可知根節點為第一個元素1,在中序遍歷序列中找到1對應位置,

則1的左邊就是左子樹324,右邊就是右子樹56;

在找到前序遍歷序列中從第二個位置開始往後找相同數目的節點為左子樹234,剩餘的就是右子樹序列65,

再根據前序遍歷規則可知,左子樹序列裡第一個就是左子樹的根節點2,右子樹序列裡的第一個就是有右子樹的根節點5,

再根據中序遍歷序列可知,左子樹的根節點2左邊的一定是以其為根節點的左子樹序列3,右邊就是以其為根節點的右子樹序列4,

右子樹的根節點5左邊的一定是以其為根節點的右子樹序列6,直至序列為空,就可以完整重建二叉樹了

如圖:

程式碼

程式碼實現:

定義節點:

#include<iostream>
#include<stdlib.h>
using namespace std;
//定義一棵二叉樹的節點
struct BTreeNode
{
	int value;
	BTreeNode * left;
	BTreeNode* right;
};

函式實現

BTreeNode * RebuildTree(int* PreOrder,int* InOrder,int length)
{
	//判斷輸入值是否合法
	if(PreOrder == NULL || InOrder == NULL || length<=0)
	{
		return NULL;
	}
	else
	{
		return RebuildCore(PreOrder,PreOrder+length-1,InOrder,InOrder+length-1);

	}
}

BTreeNode *RebuildCore(int *startPreOrder,int *endPreOrder,int *startInOrder,int *endInOrder)
{
	//2.找到前序遍歷中的根節點並建立一個節點儲存節點值
	BTreeNode *root = new BTreeNode();
	root->value = startPreOrder[0];
	root->left = NULL;
	root->right = NULL;
	//3.判斷是否找完了此次中序遍歷,若是找完了,則返回 root
	if(startInOrder == endInOrder && *startInOrder == *endInOrder)
	{
		return root;
	}
	//4.根據此根節點的值在中序遍歷中找此次節點的位置
	int * rootIn = startInOrder;
	while(*startPreOrder != *rootIn)
	{
		rootIn++;
	}
	//6.根據此根節點在中序遍歷中的位置,遞迴還原左子樹
	int leftlength = rootIn-startInOrder;
	if(leftlength>0)
	{
		root->left = RebuildCore(startPreOrder+1,startPreOrder+leftlength,startInOrder,startInOrder+leftlength-1);

	}
	//此處千萬不要錯寫成 else if 因為若是這樣,判斷滿足上面的遞迴條件,則進入遞迴還原左子樹,當左子樹完全被還原後,再調回這個點的時候,就不會繼續執行 else if 語句了,因為上面的條件已經滿足,所以右子樹將沒辦法還原了  
	if(leftlength+startInOrder < endInOrder)//左子樹長度加上中序的起始位置後若仍然小於整個中序長度則說明該節點還存在右子樹,所以繼續遞迴還原右子樹
	{//7.根據此根節點在中序遍歷中的位置,遞迴還原右子樹
		root->right = RebuildCore(startPreOrder+leftlength+1,endPreOrder,startInOrder+leftlength+1,endInOrder);
	}
	return root;
}
後序遍歷
void PostOrder(BTreeNode *root)
{
	if(root->left != NULL)
	{
		PostOrder(root->left);

	}
	if(root->right != NULL)
	{
		PostOrder(root->right);
	}
	if(root != NULL)
	{
		cout<<root->value<<" ";
	}

}

測試程式碼
int main()
{
	int preorder[] = {1,2,3,4,5,6};
	int inorder[] = {3,2,4,1,6,5};

	BTreeNode *root = RebuildTree(&preorder[0],&inorder[0],6);
	PostOrder(root);//324651
	cout<<endl;
	system("pause");
	return 0 ;

}

測試結果: