的实地观测,可导致一个干净的实现:
- 如果有
n
红色节点,那么将有2个ñ树(这忽略其中红色节点是叶的情况 - - 这些可能不重要,可以通过预处理步骤消除)。
- 0和2 Ñ之间的任何数
k
- 1可以表示一个配置 - 在第i个红色节点(即是否保留向左或右子树)的决定被指示由第位k
。该位可以使用逐位操作,例如等来容易地获得。用0
比较k & (1 << i)
可以由一个生成树一个主要功能是这样的:
void spawnAllTrees(baseTree) {
int nRed = countRedNodes(baseTree);
// this assigns to each red node an index between 0 and nRed - 1
// (e.g. according to a pre-order tree traversal).
// it computes a hash map denoted as "redIndex" which
// stores the mapping from Node to int
computeRedIndices(baseTree);
for (int k = 0; k < (1 << nRed); k++) {
crtTree = spawnTree(baseTree, k);
}
}
为spawnTree的代码将是:
Node spawnTree(baseTreeNode, k) {
if (baseTreeNode.isRed()) {
idx = redIndex[baseTreeNode];
if (!bitIsSet(k, idx)) {
return spawnTree(baseTreeNode->left(), k);
} else {
return spawnTree(baseTreeNode->right(), k);
} else {
return new Node(baseTreeNode->value(),
spawnTree(baseTreeNode->left(), k),
spawnTree(baseTreeNode->right(), k));
}
}
编辑:
更改字母有点 - 增加一个计数器来确定当前的红色节点索引是无效的。在某个红色节点的不同决策可能会使另一个红色节点接收不同配置的不同索引。
做一元的brances,例如'n5'或'n6'必须特别是左右分支,否则它们可以是?它也必须表示为树或可以用'()'表示。如果是,则转换为BNF并生成所有的模式,例如'S = A n1(n2 B)。 A = n3 | N4。 B = n5 | n6.' –
谢谢@GuyCoder,'n5'和'n6'不一定要在特定的左侧和右侧。另一方面,我发现我很难明白你的观点。无论如何,你能否详细阐述它..?谢谢! – computereasy