如何构建BST给后序遍历 [英] How to construct BST given post-order traversal
问题描述
我知道有很多方法可以构建从pre序遍历树(作为一个数组)。更常见的问题是要构造它,因为中序和pre阶遍历。在这种情况下,虽然序遍历是多余的,它绝对会让事情变得更加容易。任何人都可以给我一个想法如何做到这一点的后序遍历?既迭代和递推解决方案是必需的。
I know there are ways to construct a tree from pre-order traversal (as an array). The more common question is to construct it, given the inorder and pre-order traversals. In this case, although the inorder traversal is redundant, it definitely makes things easier. Can anybody give me an idea how to do it for a post-order traversal? Both iterative and recursive solutions are required.
我试着用栈做反复,但不能在所有得到的逻辑正确,所以得到了一个可怕的混乱的树。同去的递归。
I tried to do it iteratively using stack, but couldn't at all get the logic right, so got a horrible messy tree. Same went for recursion.
推荐答案
如果您有从BST的后序遍历数组,你知道根是数组的最后一个元素。根的左子占据了阵列的第一部分,和由条目不是根小的。然后,遵循正确的孩子,组成元素不是根大的。 (两个孩子可能是空的)。
If you have an array from a post-order traversal of a BST, you know that the root is the last element of the array. The left child of the root takes up the first part of the array, and consists of entries smaller than the root. Then follows the right child, consisting of elements larger than the root. (Both children may be empty).
________________________________
| | |R|
--------------------------------
left child right child root
因此,主要的问题是要找到的点的左子端部和右开始
So the main problem is to find the point where the left child ends and the right begins.
两个儿童也从它们的后序遍历,从而可以获得构造它们被以相同的方式完成的,递归
Both children are also obtained from their post-order traversal, so constructing them is done in the same way, recursively.
BST fromPostOrder(value[] nodes) {
// No nodes, no tree
if (nodes == null) return null;
return recursiveFromPostOrder(nodes, 0, nodes.length - 1);
}
// Construct a BST from a segment of the nodes array
// That segment is assumed to be the post-order traversal of some subtree
private BST recursiveFromPostOrder(value[] nodes,
int leftIndex, int rightIndex) {
// Empty segment -> empty tree
if (rightIndex < leftIndex) return null;
// single node -> single element tree
if (rightIndex == leftIndex) return new BST(nodes[leftIndex]);
// It's a post-order traversal, so the root of the tree
// is in the last position
value rootval = nodes[rightIndex];
// Construct the root node, the left and right subtrees are then
// constructed in recursive calls, after finding their extent
BST root = new BST(rootval);
// It's supposed to be the post-order traversal of a BST, so
// * left child comes first
// * all values in the left child are smaller than the root value
// * all values in the right child are larger than the root value
// Hence we find the last index in the range [leftIndex .. rightIndex-1]
// that holds a value smaller than rootval
int leftLast = findLastSmaller(nodes, leftIndex, rightIndex-1, rootval);
// The left child occupies the segment [leftIndex .. leftLast]
// (may be empty) and that segment is the post-order traversal of it
root.left = recursiveFromPostOrder(nodes, leftIndex, leftLast);
// The right child occupies the segment [leftLast+1 .. rightIndex-1]
// (may be empty) and that segment is the post-order traversal of it
root.right = recursiveFromPostOrder(nodes, leftLast + 1, rightIndex-1);
// Both children constructed and linked to the root, done.
return root;
}
// find the last index of a value smaller than cut in a segment of the array
// using binary search
// supposes that the segment contains the concatenation of the post-order
// traversals of the left and right subtrees of a node with value cut,
// in particular, that the first (possibly empty) part of the segment contains
// only values < cut, and the second (possibly empty) part only values > cut
private int findLastSmaller(value[] nodes, int first, int last, value cut) {
// If the segment is empty, or the first value is larger than cut,
// by the assumptions, there is no value smaller than cut in the segment,
// return the position one before the start of the segment
if (last < first || nodes[first] > cut) return first - 1;
int low = first, high = last, mid;
// binary search for the last index of a value < cut
// invariants: nodes[low] < cut
// (since cut is the root value and a BST has no dupes)
// and nodes[high] > cut, or (nodes[high] < cut < nodes[high+1]), or
// nodes[high] < cut and high == last, the latter two cases mean that
// high is the last index in the segment holding a value < cut
while (low < high && nodes[high] > cut) {
// check the middle of the segment
// In the case high == low+1 and nodes[low] < cut < nodes[high]
// we'd make no progress if we chose mid = (low+high)/2, since that
// would then be mid = low, so we round the index up instead of down
mid = low + (high-low+1)/2;
// The choice of mid guarantees low < mid <= high, so whichever
// case applies, we will either set low to a strictly greater index
// or high to a strictly smaller one, hence we won't become stuck.
if (nodes[mid] > cut) {
// The last index of a value < cut is in the first half
// of the range under consideration, so reduce the upper
// limit of that. Since we excluded mid as a possible
// last index, the upper limit becomes mid-1
high = mid-1;
} else {
// nodes[mid] < cut, so the last index with a value < cut is
// in the range [mid .. high]
low = mid;
}
}
// now either low == high or nodes[high] < cut and high is the result
// in either case by the loop invariants
return high;
}
这篇关于如何构建BST给后序遍历的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!