的實地觀測,可導致一個乾淨的實現:
- 如果有
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