面試題6:重建二叉樹,輸入某二叉樹的前序遍歷和中序遍歷的結果,重建出該二叉樹。

假設輸入的前序遍歷和中序遍歷的結果中都不含重複數字。

例如:輸入前序遍歷序列{1,2,4,7,3,5,6,8},和中序遍歷序列{4,7,2,1,5,3,8,6}

要求重建出該二叉樹,並輸出其頭結點。

二叉樹結點的定義如下:

struct BinaryTreeNode
{
	int 	        m_nValue;
	BinaryTreeNode* m_pLeft;
	BinaryTreeNode* m_pRight;	
}
思路分析:首先清楚這幾種遍歷的順序,前序遍歷:根左右;中序遍歷:左根右;即前序遍歷序列的第一個結點總是根結點。
中序遍歷的根節點在中間,且根節點左側序列是左子樹的結點值,右側序列是右子樹的結點值。

所以首要任務是;找出根結點的值以及左子樹結點的值和右子樹結點的值。然後用遞歸的方法去完成。

c++代碼實現:

BinaryTreeNode* 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);
}

BinaryTreeNode* ConstructCore
(
	int* startPreorder,int* endPreorder,int* startInorder,int* endInorder
)
{
	//1.前序遍歷的第一個數字是根結點的值。以此根結點來創建新的二叉樹,只有根結點,左右子樹爲空。
	int rootValue = startPreorder[0];
	BinaryTreeNode* root = new BinaryTreeNode();
	root->m_nValue=rootValue;
	root->m_pLeft=root->m_pRight=Null;
	
	if(startPreorder ==endPreorder)
	{
		if(startInorder == endInorder && *startPreorder == *startInorder)
			return root;
		else
			throw std::exception("Invalid input.");
	}
	
	//2.在中序遍歷中找到根結點的值,在遍歷序列中劃分出左、右子樹對應的子序列。
	int* rootInodrer = startInorder;
	while(rootInodrer<=endInorder && *rootInodrer!=rootValue)
	{
		++rootInodrer;//找到根結點在中序遍歷中的位置
	}
	
	if(rootInodrer == endInorder && *rootInodrer!=rootValue)
	{
		throw std::exception("Invalid input.");
	}
	
	int leftLength = rootInodrer - startInorder;
	int* leftPreorderEnd = startPreorder+leftLength;
	//把構建二叉樹的大問題分解成構建左右子樹的兩個小問題。用遞歸的方式來解決。
	if(leftLength>0)//3.構建左子樹
	{
		//新的左子樹的前序遍歷序列從(startPreorder+1)到(leftPreorderEnd)結束。實現了在遍歷序列中對左右子樹的劃分。
		//新左子樹的中序遍歷序列從(startInorder)到(rootInodrer-1)結束。故可以用遞歸的方法來實現左子樹的創建。
		
		root->m_pLeft = ConstructCore(startPreorder+1,leftPreorderEnd,startInorder,rootInodrer-1);//遞歸調用來分別構建左右子樹
	}
	if(leftLength<endPreorder-startPreorder)//4.構建右子樹
	{
		//新的右子樹的前序遍歷序列從(leftPreorderEnd+1)到(endPreorder)結束。
		//新左子樹的中序遍歷序列從(rootInodrer+1)到(endInorder)結束。故可以用遞歸的方法來實現右子樹的創建。
		root->m_pRight = ConstructCore(leftPreorderEnd+1,endPreorder,rootInodrer+1,endInorder);
	}
	return root;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章