订购:SAEUYQRPDFKLM
预购:FASQYEUPRDKLM
我很困惑如何处理中间部分。似乎没有任何组合有效,帮助?有人有窍门吗?我该如何处理?我已经为此打了2个小时。
我必须恢复这棵树。
正确的结果是
我将尝试为您提供一般性解释,而不是为您的示例提供具体解释。我认为它更有用,毕竟你可以用你的具体案例测试算法,看看算法是否有效并更好地理解。
你可以用递归的方式思考这个问题。
为了解决这个问题,我们可以就一些变量达成一致
preorder
: 包含前序遍历的数组inorder
: 包含中序遍历的数组l_p
preorder
:数组中的左索引r_p
preorder
:数组中的右索引l_i
inorder
:数组中的左索引r_i
inorder
:数组中的右索引在您的具体示例中,第一个实例是l_p = l_i = 0
and r_p = r_i = 12
。
这可以方便解释:
index 0 1 2 3 4 5 6 7 8 9 10 11 12
preorder: F A S Q Y E U P R D K L M
inorder: S A E U Y Q R P D F K L M
< left > ^ < right >
|
this is the root
一个非常重要的事实是要认识到当前树的根总是preorder[l_p]
,第一次是F
。现在,您必须识别树的左右分支,它们在inorder
数组中被清楚地区分(见上图)。为了知道这一点,您在inorder
数组中搜索包含 root 的索引F
;这个指数是9
。我们可以看到根在 之后的九个位置l_i
。让i
一个变量表示相对于多少个位置l_i
是树的根。
所以,左树的键在和inorder
之间,右树的键在和之间。0
8
10
12
为了递归地构建你有的左树l_p = l_p + 1
,因为你已经看到了根,and r_ p = l_p + i =
,但是数组inorder
由l_i = 0
and分隔r_i = l_i + i - 1 =8
。
同理,右树在andpreorder
之间,而在数组中它在and之间。l_p = l_p + i + 1 = 10
r_p = r_p = 12
inorder
l_i = l_i + i + 1
r_i
有了这一切(有点复杂),我们可以勾勒出一个算法:
Node * build_tree(int preorder[], int l_p, int r_p,
int inorder[], int l_i, int r_i)
{
if (l_p > r_p)
return nullptr; // empty tree
Node * root = new Node;
root->key = preorder[l_p];
int i = 0; // now we search index of preorder[l_p] in inorder array
for (int j = l_i; j <= r_i; ++j)
if (inorder[j] == preorder[l_p])
{
i = j - l_i; // the root is at l_i + i
break; // always breaks if everything is ok
}
root->left = build_tree(preorder, l_p + 1, l_p + i,
inorder, l_i, l_i + (i - 1));
root->right = build_tree(preorder, l_p + i + 1, r_p,
inorder, l_i + i + 1, r_i);
return root;
}