七:重建二叉樹(依據先序遍歷(或者後序遍歷)和中序遍歷重建二叉樹)
對於一顆二叉樹。能夠依據先序遍歷(或者後序遍歷)和中序遍歷(樹中不含反復的數字)又一次還原出二叉樹。
解析:
1. 先序遍歷序列的第一個元素必然是根節點,能夠由此獲取二叉樹的根節點。
2. 依據根節點,在中序遍歷序列中查找該節點,由中序遍歷的性質可知,中序遍歷中該根節點左邊的序列必然在根節點的左子樹中。而根節點右邊的序列必然在右子樹中。由此能夠知道先序遍歷中左子樹以及右子樹的起止位置。
3. 找到了左右子樹前序遍歷和中序遍歷再用相同的方法分別構建左右子樹,典型的遞歸思想。
代碼例如以下:
BinaryTreeNode* ConstructCore
(
int* startPreorder, int* endPreorder,
int* startInorder, int* endInorder
)
{
// 前序遍歷序列的第一個數字是根結點的值
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.");
}
// 在中序遍歷中找到根結點的值
int* rootInorder = startInorder;
while(rootInorder <= endInorder && *rootInorder != rootValue)
++ rootInorder;
//推斷是否找到根節點
if(rootInorder == endInorder && *rootInorder != rootValue)
throw std::exception("Invalid input.");
int leftLength = rootInorder - startInorder;
int* leftPreorderEnd = startPreorder + leftLength;
if(leftLength > 0)
{
// 構建左子樹
root->m_pLeft = ConstructCore(startPreorder + 1, leftPreorderEnd,
startInorder, rootInorder - 1);
}
if((leftLength+ startPreorder)< endPreorder ) {
// 構建右子樹
root->m_pRight = ConstructCore(leftPreorderEnd + 1, endPreorder,
rootInorder + 1, endInorder);
}
return root;
}
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);
}
註:《劍指offer》學習總結
七:重建二叉樹(依據先序遍歷(或者後序遍歷)和中序遍歷重建二叉樹)