首先,我假设所有元素都是不同的。序列化的数量不会告诉您带有元素的树的形状[3,3,3,3,3]
。当然,可以用重复的元素重建一些树。我不知道有什么好的充分条件。
继续负面结果,您不能仅凭其前序和后序序列完全重建二叉树。[1,2]
预购,[2,1]
后购必须1
是根源,但2
可以是左孩子或右孩子。如果您不关心这种歧义性,则可以使用以下算法来重构树:
- 令为前序遍历,为后序遍历。我们必须具有,这是树的根。[ y n,… ,y 1 ] x 1 = y 1[ x1个,… ,xñ][ yñ,… ,y1个]X1个= y1个
- y 2 x 2 = y 2 [ x 2,… ,x n ] [ y n,… ,y 2 ]X2是根的最左子,而是根的最右子。如果,则根节点是一元的;在和上以构建单个子树。ÿ2X2= y2[ x2,… ,xñ][ yñ,… ,y2]
- 否则,令和为索引,使得和。是左子树的前序遍历,是右子树的前序遍历,类似地,是后序遍历。左子树具有元素,而右子树具有元素。为每个子树递归一次。
顺便说一下,该方法可以推广到具有任意分支的树。使用任意分支,找出左侧子树的范围,并从两个列表中都切掉其元素,然后重复以从左侧切出第二个子树,依此类推。j x 2 = y i y 2 = x j [ x 2,… ,x j − 1 ] [ x j,… ,x n ] j − 2 = n − i + 1 i − 2 = n − j + 1 j − 2一世ĴX2= y一世ÿ2= xĴ[ x2,… ,xj − 1][ xĴ,… ,xñ]j − 2 = n − i + 1i − 2 = n − j + 1
j − 2
如前所述,运行时间为,最差情况为(在有两个孩子的情况下,我们逐行搜索每个列表)。如果对列表进行预处理以构建从元素值到输入列表中位置的有限映射结构,则可以将其转换为。也可以使用数组或有限映射从索引到值。坚持使用全局索引,以便递归调用将接收整个地图,并以范围作为参数来知道要采取的行动。Θ (n 2)O (nØ (ñ2)Θ (n2)nØ (ñ升克(Ñ ))ñ升克(Ñ )
通过预遍历和有序遍历,可以按以下方式重建树:[ z 1,… ,z n ][ x1个,… ,xñ][ z1个, … ,zñ]
- 根是预遍历的头。X1个
- 令为使的索引。然后是左子项的有序遍历,是右子项的有序遍历。根据元素的数量,是左子元素的预遍历,是右子元素的预遍历。递归以建立左右子树。z k = x 1 [ z 1,… ,z k − 1 ] [ z k + 1,… ,z n ] [ x 2,… ,x k ] [ x k + 1,… ,x n ]ķžķ=x1个[z1个,… ,zk − 1][zk + 1, … ,zñ][ x2,… ,xķ][ xk + 1,… ,xñ]
再次,该算法如上所述为,如果将列表预处理为从值到位置的有限映射,则可以在执行。O (nØ (ñ2)Ø (ñ升克(Ñ ))
后订单加订单当然是对称的。