简体   繁体   English

如何在给定深度和后序遍历的情况下构造一棵树,然后打印其前序遍历

[英]How to construct a tree given its depth and postorder traversal, then print its preorder traversal

I need to construct a tree given its depth and postorder traversal, and then I need to generate the corresponding preorder traversal.我需要构造一棵给定深度和后序遍历的树,然后我需要生成相应的前序遍历。 Example:例子:

Depth: 2 1 3 3 3 2 2 1 1 0
Postorder: 5 2 8 9 10 6 7 3 4 1
Preorder(output): 1 2 5 3 6 8 9 10 7 4

I've defined two arrays that contain the postorder sequence and depth.我定义了两个包含后序序列和深度的 arrays。 After that, I couldn't come up with an algorithm to solve it.在那之后,我想不出一个算法来解决它。

Here's my code:这是我的代码:

int postorder[1000];
int depth[1000];
string postorder_nums;
getline(cin, postorder_nums);
istringstream token1(postorder_nums);
string tokenString1;
int idx1 = 0;
while (token1 >> tokenString1) {
    postorder[idx1] = stoi(tokenString1);
    idx1++;
}
string depth_nums;
getline(cin, depth_nums);
istringstream token2(depth_nums);
string tokenString2;
int idx2 = 0;
while (token2 >> tokenString2) {
    depth[idx2] = stoi(tokenString2);
    idx2++;
}
Tree tree(1);

I won't give you the code, but some hints how to solve the problem.我不会给你代码,而是一些提示如何解决这个问题。

First, for postorder graph processing you first visit the children, then print (process) the value of the node.首先,对于后序图处理,您首先访问子节点,然后打印(处理)节点的值。 So, the tree or subtree parent is the last thing that is processed in its (sub)tree.因此,树或子树父是在其(子)树中处理的最后一件事。 I replace 10 with 0 for better indentation:我将 10 替换为 0 以获得更好的缩进:

2 1 3 3 3 2 2 1 1 0
--------------------
5 2 8 9 0 6 7 3 4 1

As explained above, node of depth 0, or the root, is the last one.如上所述,深度为 0 的节点或根是最后一个。 Let's lower all other nodes 1 level down:让我们将所有其他节点降低 1 级:

2 1 3 3 3 2 2 1 1 0
-------------------
                  1
5 2 8 9 0 6 7 3 4 

Now identify all nodes of depth 1, and lower all that is not of depth 0 or 1:现在识别深度为 1 的所有节点,并降低所有深度不为 0 或 1 的节点:

2 1 3 3 3 2 2 1 1 0
-------------------
                  1
  2           3 4 
5   8 9 0 6 7 

As you can see, (5,2) is in a subtree, (8,9,10,6,7,3) in another subtree, (4) is a single-node subtree.如您所见,(5,2)在一个子树中,(8,9,10,6,7,3)在另一个子树中,(4)是单节点子树。 In other words, all that is to the left of 2 is its subtree, all to the right of 2 and to the left of 3 is in the subtree of 3, all between 3 and 4 is in the subtree of 4 (here: empty).换句话说,2的左边都是它的子树,2的右边和3的左边都是3的子树,3到4之间的都是4的子树(这里:空)。

Now lets deal with depth 3 in a similar way:现在让我们以类似的方式处理深度 3:

2 1 3 3 3 2 2 1 1 0
-------------------
                  1
  2           3 4 
5         6 7 
    8 9 0  
  • 2 is the parent for 2; 2 是 2 的父级;
  • 6 is the parent for 8, 8, 10; 6 是 8、8、10 的父级;
  • 3 is ahe parent for 6,7; 3 是 6,7 的父母;

or very explicitly:或非常明确:

2 1 3 3 3 2 2 1 1 0
-------------------
                  1
   /           / /
  2           3 4 
 /         / /
5         6 7 
     / / /
    8 9 0  

This is how you can construct a tree from the data you have.这就是您可以从您拥有的数据中构建一棵树的方法。

EDIT编辑

Clearly, this problem can be solved easily by recursion.显然,这个问题可以很容易地通过递归来解决。 In each step you find the lowest depth, print the node, and call the same function recursively for each of its subtrees as its argument, where the subtree is defined by looking for current_depth + 1. If the depth is passed as another argument, it can save the necessity of computing the lowest depth.在每个步骤中,您找到最低深度,打印节点,并为其每个子树递归调用相同的 function 作为其参数,其中子树是通过查找 current_depth + 1 来定义的。如果深度作为另一个参数传递,它可以省去计算最低深度的必要性。

You can do this actually without constructing a tree.您实际上可以在不构建树的情况下执行此操作。

First note that if you reverse the postorder sequence, you get a kind of preorder sequence, but with the children visited in opposite order.首先请注意,如果您反转后序序列,您会得到一种前序序列,但访问的孩子顺序相反。 So we'll use this fact and iterate over the given arrays from back to front, and we will also store values in the output from back to front.所以我们将使用这个事实并从后到前迭代给定的 arrays,我们还将从后到前将值存储在 output 中。 This way at least the order of siblings will come out right.这样至少兄弟姐妹的顺序会正确。

The first value we get from the input will thus always be the root value.因此,我们从输入中获得的第一个值将始终是根值。 Obviously we cannot store this value at the end of the output array, as it really should come first.显然,我们不能将此值存储在 output 数组的末尾,因为它确实应该排在第一位。 But we will put this value on a stack until all other values have been processed.但是我们将把这个值放在一个堆栈上,直到所有其他值都被处理完。 The same will happen for any value that is followed by a "deeper" value (again: we are processing the input in reversed order).对于后面跟着“更深”值的任何值都会发生同样的情况(同样:我们正在以相反的顺序处理输入)。 But as soon as we find a value that is not deeper, we flush a part of the stack into the output array (also filling it up from back to front).但是一旦我们找到一个不深的值,我们就会将堆栈的一部分刷新到 output 数组中(也从后到前填充它)。

When all values have been processed, we just need to flush the remaining values from the stack into the output array.处理完所有值后,我们只需要将堆栈中的剩余值刷新到 output 数组中。

Now, we can optimise our space usage here: as we fill the output array from the back, we have free space at its front to use as the stack space for this algorithm.现在,我们可以在这里优化空间使用:当我们从后面填充 output 数组时,我们在其前面有空闲空间用作该算法的堆栈空间。 This has as nice consequence that when we arrive at the end we don't need to flush the stack anymore, because it is already there in the output, with every value where it should be.这有一个很好的结果,当我们到达最后时,我们不再需要刷新堆栈,因为它已经存在于 output 中,每个值都应该存在。

Here is the code for this algorithm where I did not include the input collection, which apparently you already have working:这是该算法的代码,其中我没有包含输入集合,显然您已经在使用它:

// Input example
int depth[] = {2, 1, 3, 3, 3, 2, 2, 1, 1, 0};
int postorder[] = {5, 2, 8, 9, 10, 6, 7, 3, 4, 1};
// Number of values in the input
int n = sizeof(depth)/sizeof(int);

int preorder[n]; // This will contain the ouput
int j = n; // index where last value was stored in preorder
int stackSize = 0; // how many entries are used as stack in preorder
for (int i = n - 1; i >= 0; i--) {
    while (depth[i] < stackSize) {
        preorder[--j] = preorder[--stackSize]; // flush it
    }
    preorder[stackSize++] = postorder[i]; // stack it
}
// Output the result:
for (int i = 0; i < n; i++) {
    std::cout << preorder[i] << " ";
}
std::cout << "\n";

This algorithm has an auxiliary space complexity of O(1) -- so not counting the memory needed for the input and the output -- and has a time complexity of O(n).该算法的辅助空间复杂度为 O(1)——因此不计算输入所需的 memory 和 output——并且时间复杂度为 O(n)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM