How to construct BST given post-order traversal

匿名 (未验证) 提交于 2019-12-03 01:00:01

问题:

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.

回答1:

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  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 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  cut) return first - 1;      int low = first, high = last, mid;      // binary search for the last index of a value  cut, or (nodes[high]  cut) {          // check the middle of the segment         // In the case high == low+1 and nodes[low]  cut) {             // The last index of a value 


回答2:

You don't really need the inorder traversal. There's a simple way to reconstruct the tree given only the post-order traversal:

  1. Take the last element in the input array. This is the root.
  2. Loop over the remaining input array looking for the point where the elements change from being smaller than the root to being bigger. Split the input array at that point. This can also be done with a binary search algorithm.
  3. Recursively reconstruct the subtrees from those two sub-arrays.

This can easily be done either recursively or iteratively with a stack, and you can use two indices to indicate the start and end of the current sub-array rather than actually splitting the array.



回答3:

Postorder traversal goes like this:

visit left visit right print current. 

And inorder like this:

visit left print current visit right 

Let's take an example:

        7      /     \     3      10    / \     / \   2   5   9   12              /             11 

Inorder is: 2 3 5 7 9 10 11 12

Postorder is: 2 5 3 9 11 12 10 7

Iterate the postorder array in reverse order and keep splitting the inorder array around where that value is. Do this recursively and that will be your tree. For example:

current = 7, split inorder at 7: 2 3 5 | 9 10 11 12 

Look familiar? What is on the left is the left subtree and what is on the right is the right subtree, in a pseudo-random order as far as the BST structure is concerned. However, you now know what your root is. Now do the same for the two halves. Find the first occurrence (from the end) of an element from the left half in the postorder traversal. That will be 3. Split around 3:

current = 3, split inorder at 3: 2 | 5 ... 

So you know your tree looks like this so far:

   7  / 3 

This is based on the facts that a value in the postorder traversal will always appear after its children have appeared and that a value in the inorder traversal will appear between its children values.



回答4:

Don't loop over anything. Last element is your Root. then taking array backwards follow insertion rules of BST.

eg:-    given just the postorder -- 2 5 3 9 11 12 10 7            7          \           10          ----         7          \           10            \             12          -----         7          \           10            \             12            /           11          -------         7          \           10          /  \         9    12            /           11          --------         7       /  \      3    10     / \  /  \    2   5 9  12            /           11 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!