【发布时间】:2017-08-06 05:32:24
【问题描述】:
我目前正在尝试提出一种算法来实现完整的二叉树(二叉树与 两个或没有孩子)动态。 代码将在 C++ 中实现。我可以手动实现我的树,但正如我所拥有的那样 我需要自动完成 900 棵不同的树。在这里我需要一些想法、提示和帮助。
让我们开始解释我在做什么: 我从图形合并过程中得到我的树。我根据成本函数合并图中的两个节点。的标签 更大的节点将是合并节点的标签(我的图形节点具有空间大小)。 所以我最终得到一个包含合并节点的向量 以及新节点的剩余标签(注意剩余标签基于节点大小和 与注号无关)。向量中的最后两个条目是合并在一起的第一个节点。下一个 更高的条目是合并节点的剩余标签。这将按此顺序继续,直到只有根节点(第一个条目) 离开了。
第一个问题是,我的图表有不同数量的节点。所以我的 合并过程中的树具有不同的大小,即我的向量具有不同的大小。
为了让您了解它的外观,请参见以下示例:
treelist 向量(左边的数字,所以是一维向量):
27| root (0)--> root (27 and 33 are merged, remaining label is 27)
33| right (1)
27| left (2)
27| subroot (3)--> t1 (3 and 27 are merged, remaining label is 27)
27| right (4)
3 | left (5)
27| subroot (6) --> t2 (10 and 27 are merged, remaining label is 27)
27| right (7)
10| left (8)
27| subroot (9) --> t3 (17 and 27 are merged, remaining label is 27)
27| right (10)
17| left (11)
33| subroot (12)--> t4 (31 and 33 are merged, remaining label is 33)
33| right (13)
31| left (14)
由上述树列表向量以 ASCII 格式构建的树:
root
27
/ \
27(t1) 33(t4)
/ \ / \
3 27(t2) 31 33
/ \
10 27(t3)
/ \
17 27
同样,我拥有的实际向量只是左侧的数字。左/右这两个词是指 到它连接到根/子根的一侧。括号内的数字是 向量中的相对位置。
我的树遵循两条规则:
- t1 始终连接到根
- tk-1 绝不是 tk 的较低连接,例如t1 永远不是 t2 的下连接
我现在要做的是创建一个通用算法来构建像上面这样的树 不同的尺寸(最多约 15-20)。这里的大小是指内部节点的数量,对于 上面的树是 4。
我的想法是/是通过给定树大小的 switch-case 创建这些树。 不幸的是,我最终在这些案例中得到了很多 if 语句 情况下它几乎无法管理了。
请参阅我的伪算法以了解以下一般情况(树是自下而上构建的):
PseudoCode: (Note that for building the tree the first insert is the left node and the second is the right node)
switch(treesize)
case 3: root = vector[0]; //represents root node
t1 = vector[3]; //represents t1
t2 = vector[6]; //represents t2
t3 = vector[9]; //represents t3
// create node t3
t3->insert(vector[11]); t3->insert(vector[10]);
// create node t2
if (t3 == vector[8]) {t2->addChild(t3); t2->insert(vector[7]);}
if (t3 == vector[7]) {t2->insert(vector[8]); t2->addChild(t3);}
else {t2->insert(vector[8]); t2->insert(vector[7]);}
// create node t1
if (t3 == vector[5] && t2 != vector[4]) {t1->addChild(t3); t2->insert(vector[4]);}
if (t3 == vector[4] && t2 != vector[5]) {t1->insert(vector[5]); t1->addChild(t3);}
if (t2 == vector[5] && t3 != vector[4]) {t1->addChild(t2); t1->insert(vector[4]);}
if (t2 == vector[4] && t3 != vector[5]) {t1->insert(vector[5]); t1->addChild(t2);}
if (t3 == vector[5] && t2 == vector[4]) { t1->addChild(t3); t1->addChild(t2);}
if (t2 == vector[5] && t3 == vector[4]) { t1->addChild(t2); t1->addChild(t3);}
else {t1->insert(vector[5]); t1->insert(vector[4]);}
// create root (Note that t1 is always connected to the root)
if (t3 == vector[2]) {root->addChild(t3); root->addChild(t1);}
if (t2 == vector[2]) {root->addChild(t2); root->addChild(t1);}
if (t3 == vector[1]) {root->addChild(t1); root->addChild(t3);}
if (t2 == vector[1]) {root->addChild(t1); root->addChild(t2);}
if (t1 == vector[2] && (t3 && t2) != vector[1]) {root->addChild(t1); root->insert(vector[1]);
if (t1 == vector[1] && (t3 && t2) != vector[2]) {root->insert(vector[2]); root->addChild(t1);}
case 4: root = vector[0]; //represents the root node
t1 = vector[3]; //represents t1
t2 = vector[6]; //represents t2
t3 = vector[9]; //represents t3
t4 = vector[12]; //represents t4
// create t4
t4->insert(vector[14]); t3->insert(vector[13]);
// create t3
if (t4 == vector[11]) {t3->addChild(t4); t3->insert(vector[10]);}
if (t4 == vector[10]) {t3->insert(vector[11]); t3->addChild(t4);}
else {t3->insert(vector[11]); t3->insert(vector[10]);}
// create t2
if (t4 == vector[8] && t3 != vector[7]) {t2->addChild(t4); t2->insert(vector[7]);}
if (t4 == vector[7] && t3 != vector[8]) {t2->insert(vector[8]); t2->addChild(t4);}
if (t3 == vector[8] && t4 != vector[7]) {t2->addChild(t3); t2->insert(vector[7]);}
if (t3 == vector[7] && t4 != vector[8]) {t2->insert(vector[8]); t2->addChild(t3);}
if (t4 == vector[8] && t3 == vector[7]) {t2->addChild(t4); t2->addChild(t3);}
if (t3 == vector[8] && t4 == vector[7]) {t2->addChild(t3); t2->addChild(t4);}
else {t2->insert(vector[8]); t2->insert(vector[7]);}
// create t1
if (t4 == vector[5] && t3 != vector[4] && t2 != vector[4]) {t1->addChild(t4); t1->insert(vector[4]);}
if (t4 == vector[4] && t3 != vector[5] && t2 != vector[5]) {t1->insert(vector[5]); t1->addChild(t4);}
if (t3 == vector[5] && t4 != vector[4] && t2 != vector[4]) {t1->addChild(t3); t1->insert(vector[4]);}
if (t3 == vector[4] && t4 != vector[5] && t2 != vector[5]) {t1->insert(vector[5]); t1->addChild(t3);}
if (t2 == vector[5] && t4 != vector[4] && t3 != vector[4]) {t1->addChild(t5); t1->insert(vector[4]);}
if (t2 == vector[4] && t4 != vector[5] && t3 != vector[5]) {t1->insert(vector[5]); t1->addChild(t2);}
if (t4 == vector[5] && t3 == vector[4]) {t1->addChild(t4); t1->addChild(t3);}
if (t4 == vector[5] && t2 == vector[4]) {t1->addChild(t4); t1->addChild(t2);}
if (t3 == vector[5] && t2 == vector[4]) {t1->addChild(t3); t1->addChild(t2);}
if (t3 == vector[5] && t4 == vector[4]) {t1->addChild(t3); t1->addChild(t4);}
if (t2 == vector[5] && t3 == vector[4]) {t1->addChild(t2); t1->addChild(t3);}
if (t2 == vector[5] && t4 == vector[4]) {t1->addChild(t2); t1->addChild(t4);}
// create root (Note that t1 is always connected to the root)
if (t4 == vector[2]) {root->addChild(t4); root->addChild(t1);}
if (t3 == vector[2]) {root->addChild(t3); root->addChild(t1);}
if (t2 == vector[2]) {root->addChild(t2); root->addChild(t1);}
if (t4 == vector[1]) {root->addChild(t1); root->addChild(t4);}
if (t3 == vector[1]) {root->addChild(t1); root->addChild(t3);}
if (t2 == vector[1]) {root->addChild(t1); root->addChild(t2);}
if (t1 == vector[2] && (t4 && t3 && t2) != vector[1]) {root->addChild(t1); root->insert(vector[1]);}
if (t1 == vector[1] && (t4 && t3 && t2) != vector[2]) {root->insert(vector[2]); root->addChild(t1);}
case 5: .....
....
....
正如您所注意到的,对于更高的情况,这将是一团糟。
所以我总是要检查左节点或右节点是否可能与 子根之一。这实际上导致了所有这些 if 语句。
我现在的问题是:你知道如何以更好的方式甚至完全不同的方式来实现这个算法吗? 对此的任何建议都会有所帮助。
非常感谢您的任何帮助。
如果有什么不清楚的地方或者我应该再举一个例子,请告诉我。
请看下面我如何从图表中获取向量:
图表:
我合并两个节点的成本函数是 C = Node_A + Node_B / Edgeweight。
合并过程:
1. 12+6 -> 6
2. 24+31 -> 24
3. 6+24 -> 6
4. 6+9 -> 6
5. 6+22 -> 6
结果向量(与上面相同的属性)和树:
(Note that the first two nodes which merges are the last two entries)
6 --> root root
22 6
6 / \
6 --> t1 6(t1) 22
9 / \
6 6(t2) 9
6 --> t2 / \
24 6(t4) 24(t3)
6 / \ / \
24 --> t3 6 12 24 31
31
24
6 --> t4
12
6
也许还有一种更优雅的方法可以从合并过程中构建我的向量,以便在下一步中获得我的树。
【问题讨论】:
-
您的输入向量每个节点有3个元素,并且节点的“值”不是唯一的?这看起来可能很难做到,因为您无法唯一标识节点。如果您有多个具有该值的其他节点,则向量中的一个节点说它有一个值为
27的正确节点是不明确的。您有点需要您的向量以特定顺序(有序、前序、后序)包含节点,或者每个节点的唯一标识符及其值+分支。不过,这个问题措辞很好,很好。 -
给上面的具体例子,你怎么知道
t1和t2进入哪个顺序?假设向量中有一个顺序,在上面的示例中,它是预购还是中序是模棱两可的。 -
初始标签是否保证唯一?如果不是,那么数组[1, 1, 1, 1, 1, 1, 1, 1, 1]应该如何处理?您可以从中构建两个非同构树。
-
code will be implemented in C++相应地标记您的问题。您在寻找建议或代码建议吗?作为第一步,不要像你那样使用索引文字 - 切换到 3 的倍数(nodes 的索引,而不是subroots)(根据需要加上 1 或 2 - 儿童)。left和right似乎可以互换:认为它们是可枚举/“可迭代”而不是命名可能是有利的。
标签: c++ algorithm tree binary-tree