您可以使用标准的 DFS 和 BFS 算法,但是您可以根据需要计算它们,而不是从预先构建的树结构中获取特定节点的子节点。
对于一个 BFS 编号、高度为 H 的完整 K-ary 树,节点的第 i 个子节点 N 在深度 D 是:
K*N + 1 + i
当提供i = 0(第一个孩子)here 时,此公式的推导。
对于一个 DFS 编号、高度为 H 的完整 K-ary 树,节点的第 i 个子节点 N 深度 D 由一个更丑陋的公式给出:
N + 1 + i*step where step = (K^(H - D) - 1) / (K - 1)
下面是这个公式的粗略解释:
对于深度为 D 的节点 N 在高度为 H 的 DFS 编号 K-ary 树中,它的第一个子节点只是 N+1 因为它是深度优先遍历中要访问的下一个节点。 N 的第二个孩子将在访问以第一个孩子为根的整个子树(N+1)之后直接被访问,它本身就是一个完整的K -高度树H - (D + 1)。任何完整的K-ary 树的大小由有限几何级数的总和给出,如here 所述。所述子树的大小是第一个和第二个孩子之间的距离,实际上,它是所有兄弟姐妹之间的相同距离,因为它们的每个子树都是相同的大小。如果我们称这个距离为step,那么:
第一个孩子是N + 1
第二个孩子是N + 1 + step
第三个孩子是N + 1 + step + step
...等等。
下面是一个 Python 实现(注意:dfs 函数使用 BFS 公式,因为它正在从 DFS 转换为 BFS,反之亦然 bfs 函数。):
def dfs(K, H):
stack = list()
push, pop = list.append, list.pop
push(stack, (0, 0))
while stack:
label, depth = pop(stack)
yield label
if depth + 1 > H: # leaf node
continue
for i in reversed(range(K)):
push(stack, (K*label + 1 + i, depth + 1))
def bfs(K, H):
from collections import deque
queue = deque()
push, pop = deque.append, deque.popleft
push(queue, (0, 0))
while queue:
label, depth = pop(queue)
yield label
if depth + 1 > H: # leaf node
continue
step = (K**(H - depth) - 1) // (K - 1)
for i in range(K):
push(queue, (label + 1 + i*step, depth + 1))
print(list(dfs(2, 3)))
print(list(bfs(2, 3)))
print(list(dfs(3, 2)))
print(list(bfs(3, 2)))
上面将打印:
[0, 1, 3, 7, 8, 4, 9, 10, 2, 5, 11, 12, 6, 13, 14]
[0, 1, 8, 2, 5, 9, 12, 3, 4, 6, 7, 10, 11, 13, 14]
[0, 1, 4, 5, 6, 2, 7, 8, 9, 3, 10, 11, 12]
[0, 1, 5, 9, 2, 3, 4, 6, 7, 8, 10, 11, 12]