我为n元树实现了树遍历算法,该算法遵循预排序并使用堆栈而不是递归。在伪代码中,算法如下所示:
stack
并将根节点压入堆栈。 stack
不为空时执行以下操作。
stack
弹出项目并打印。可选:如果是人工端节点,请继续node_end
推到stack
stack
可选部分用于一个用例,其中我打印一个保留为树结构的XML文档。访问节点X
将打印开始标签,访问人工节点X_end
将打印相应的结束标签。
这里的绘制很粗糙,所以我用C ++代码给出了这棵树。
struct Node {
int id; // root is 0
std::vector<int> children; // index in the vector
}
std::array<Node, 15> tree{};
// sets all the ids, in total we have 15 nodes
for (int i = 0; i < 15; ++i)
tree[i].id = i;
// now all the children, hope one can see the tree structure
tree[0].children.push_back(1);
tree[0].children.push_back(6);
tree[1].children.push_back(2);
tree[1].children.push_back(3);
// 2 is a leaf
tree[3].children.push_back(4);
tree[3].children.push_back(5);
// 4 is a leaf
// 5 is a leaf
tree[6].children.push_back(7);
tree[6].children.push_back(9);
tree[6].children.push_back(12);
tree[7].children.push_back(8);
// 8 is a leaf
tree[9].children.push_back(10);
tree[9].children.push_back(11);
// 10 is a leaf
// 11 is a leaf
tree[12].children.push_back(13);
tree[12].children.push_back(13);
// 13 is a leaf
// 14 is a leaf
现在,运行上述算法将得到以下堆栈(一个带有人工末端节点,另一个不带有人工末端节点):
current_node | stack (simple version)
---------------------------------
- | 0
0 | 6,1
1 | 6,3,2
2 | 6,3
3 | 6,5,4
4 | 6,5
5 | 6
6 | 12,9,7
7 | 12,9,8
8 | 12,9
9 | 12,11,10
10 | 12,11
11 | 12
12 | 14,13
13 | 14
14 | -
第二个:
current_node | stack (with end nodes)
---------------------------------
- | 0
0 | 0e,6,1
1 | 0e,6,1e,3,2
2 | 0e,6,1e,3,2e
2 | 0e,6,1e,3
3 | 0e,6,1e,3e,5,4
4 | 0e,6,1e,3e,5,4e
4 | 0e,6,1e,3e,5
5 | 0e,6,1e,3e,5e
5 | 0e,6,1e,3e
3 | 0e,6,1e
1 | 0e,6
6 | 0e,6e,12,9,7
7 | 0e,6e,12,9,7e,8
8 | 0e,6e,12,9,7e,8e
8 | 0e,6e,12,9,7e
7 | 0e,6e,12,9
9 | 0e,6e,12,9e,11,10
10 | 0e,6e,12,9e,11,10e
10 | 0e,6e,12,9e,11
11 | 0e,6e,12,9e,11e
11 | 0e,6e,12,9e
9 | 0e,6e,12
12 | 0e,6e,12e,14,13
13 | 0e,6e,12e,14,13e
13 | 0e,6e,12e,14
14 | 0e,6e,12e,14e
14 | 0e,6e,12e
12 | 0e,6e
6 | 0e
0 | -
我真的希望我没有打错字。如果出现问题,请通知我。
现在我的问题是:出于优化目的,最好事先知道堆栈的最大大小。我发现以下公式可以计算单个节点所需的大小。
简单版本:
int getRequiredStackSize(Node node)
{
int sum = 0;
sum += node.children.size();
sum += getNumOfRightSiblings(node);
for (Node parent = getParent(Node); parent != NULL; parent = getParent(parent))
sum += getNumOfRightSiblings(parent);
return sum;
}
总体最大堆栈大小是所有节点的最大堆栈大小。也许可以用更少的计算来完成?
第二种情况:
int getRequiredStackSize(Node node)
{
int sum = 1; // the node's own artifical end node
sum += node.children.size();
sum += getNumOfRightSiblings(node);
for (Node parent = getParent(Node); parent != NULL; parent = getParent(parent))
sum += (1 + getNumOfRightSiblings(parent)); // the parents artifical end node as well
return sum;
}
在这里,我认为可以只计算每组兄弟姐妹中最左边的叶子的值(如何称呼同一亲代下的一组叶子?)并取其中的最大值。
第一个问题:是否可以对这些公式进行优化?
第二个问题:如何有效地计算最大值?注意:我确实自己构造了树,所以可以保留计数器等。