I am given a post order traversal of a strictly binary tree and am asked to find the pre order traversal of it. Normally, I would go a build the tree first, then find the pre order traversal. But, I was wondering if there was any way to find the pre order traversal without actually building the tree.
-
Could you give an example of the data you are dealing with please? – Har Mar 03 '20 at 14:12
3 Answers
[Edit: I first answered the question under the assumption the the given post-order was from a binary search tree with strict ordering. OP has now pointed out my error and provided an example. The basic principle of both algorithms is the same, however: Find where the boundary between the left and right subtrees is.]
Let's consider the following post-order traversal of a full binary tree where every node is either a leaf or a branch with two leaves:
1, 2, B, 3, 4, D, 5, C, A
We know that numbers are leaves and letters are branches. We also know that node A is the root, because it comes last in the post-order traversal. In order to reconstruct the pre-order traversal, we must store the root, then consider the left subtree, then the right subtree recursively.
But which nodes belong to the left, which to the right subtree? In a full or strictly binary tree with L leaves, there are N = 2·L − 1 nodes. So after storing the root, we travel the remaining subarray from the right and keep track of the number of nodes N and the number of leaves L. When the considtion N = 2·L − 1 is true, we stop. Everything we've seen belongs to the right subtree, the rest belongs to the left subtree.
So:
int is_leaf(int c)
{
return !isalpha(c); // non-alphas are leaves
}
void reconst(int **pre, const int *post, int lo, int hi)
{
printf("%d :: %d\n", lo, hi);
if (lo < hi) {
int k = --hi; // will be boundary between l/r
int root = post[k];
int leaves = 0;
int nodes = 0;
while (k > lo && nodes != 2 * leaves - 1) {
if (is_leaf(post[k - 1])) leaves++;
nodes++;
k--;
}
*(*pre)++ = root;
reconst(pre, post, lo, k);
reconst(pre, post, k, hi);
}
}
Call it like this:
int post[] = {'1', '2', 'B', '3', '4', 'D', '5', 'C', 'A'};
int n = 9;
int pre[9];
int *p = pre;
int i;
reconst(&p, post, 0, n);
for (i = 0; i < n; i++) {
printf("%c ", pre[i]);
}
puts("pre");
The code above relies on several things: (a) The pre
array must be as big as the post
array to hold the reconstructed pre-order. (b) The input must be well formed. The algorithm relies on finding a correct full subtree. (The counter is guarded against walking beyond the lower bound, but that's about it.)
[Original post that tries to find the pre-order from the post-order of a binary search tree without duplicate value, i.e. with strict ordering. Nice answer, but because misunderstood the requirements, not what OP wanted. Sorry about that.]
Say you get a post-order traversal like this:
3, 1, 7, 9, 8, 5
You know that the top node is (5) and that all smaller nodes (3, 1) are in the left branch and all larger nodes (7, 8, 9) are in the right branch. The top node goes in first in pre-order traversal. Do that, then recurse on the subarray that represents the left branch, then the right branch.
Here's a function that does that:
void reconst(int **pre, const int *post, int lo, int hi)
{
if (lo < hi) {
int k = --hi; // k will be the boundary between l/r
int parent = post[k]; // remove parent from this subarray
// find boundary between left and right branches
while (k > lo && post[k - 1] > parent) k--;
*(*pre)++ = parent; // write parent to pre-order array
reconst(pre, post, lo, k); // do the left subarray
reconst(pre, post, k, hi); // do the right subarray
}
}
The pre
array is filled via a pointer to a pointer: The top level pointer keeps track of the osition in the pre
array, the second-level pointer accesses the underlying array. (You can pass an array an an index, which you can advance instead, if that's too baroque.)
Call the function like this:
int post[] = {3, 1, 7, 9, 8, 5};
int n = 6;
int pre[6];
int *p = pre;
int i;
reconst(&p, post, 0, n);
for (i = 0; i < n; i++) {
printf("%d ", pre[i]);
}
puts("pre");
Of course, the array to hold the pre-order data must be as big as the post-order array. Code that rebuilds the tree from post-oder data would look very similar, so I don't know whether this really qualifies.

- 28,726
- 3
- 31
- 42
-
Ah! I silently took "strict binary tree" to mean "binary search tree with no duplicate values". (I was about to ask, but then didn't.) Sorry about that. – M Oehm Mar 03 '20 at 16:59
-
I've done that now and I've updated my answer. The basic principle is the same: Store the rightmost node and then try to find where the boundary between the left and right subarrays is. – M Oehm Mar 03 '20 at 17:53
If one has the ability to read the original post-order representation repeatedly, it's possible to convert a post-order traversal into a pre-order traversal using O(N²) time but constant space (a handful of counters). Examine each character of the source in sequence. If it's a node, discard it. If it's a leaf, set a "nesting" counter to zero and examine subsequent characters, incrementing the nesting counter for every leaf and decrementing it for every node. Stop when one hits the end of the source text or the value goes negative. Output the node that's there, and then work back to the leaf node one had found, incrementing and decrementing the counter in a fashion opposite what one had just done.
Every place where the counter hits zero will immediately follow a node (if it didn't, that would imply that the counter had gone negative before reaching the present location). Output that node. Once the counter has reached the leaf node one started with, output it and discard it, since neither it nor anything before it will ever be needed again.
This approach won't be as fast as other approaches, but it requires minimal memory, which may be advantageous for some purposes.

- 77,689
- 9
- 166
- 211
If you are assuming any binary tree, not a binary search one, then I believe it is not possible to get a unique preorder sequence. The reason, as I see it, is that you cannot know if the second, third, etc. nodes in the postorder sequence are roots of left or right subtrees. If the tree is a binary search one, this is clear because the order will tell you if a node is in the left or the right subtree.
If you simply want a preorder sequence that corresponds to a tree that gives a postorder sequence, then you could assume an unbalanced tree from the left side. So, simply to reverse the postorder sequence is a preorder sequence for a tree unbalanced from the left side.
For example, if your postorder sequence is "abcd"
, then "dcba"
is a valid preorder sequence for the tree:
d
/
c
/
b
/
a
Maybe is not what you want, but I think that answers your statement.

- 2,610
- 3
- 25
- 38