假设我有一个像这样的金字塔,但更大
2
4 9
4 9 6
7 7 8 9
并希望将其转换为二叉树,这意味着我们实际上想要一棵这样的树:
2
4 9
4 9 9 6
7 7 7 8 7 8 8 9
在列表格式中,结果是
2,4,9,4,9,9,6,7,7,7,8,7,8,8,9
我尝试了以下方法,但它仅适用于长度为 4 的树。作为输入,我在 txt 文件中取了一棵树。
def give_input(name):
index = 0
lis_of_listas = []
f = open(name, "r")
for x in f:
x = x.replace(' ', '')
x = x.replace('\n', '')
lista = [int(i) for i in list(x)]
if (index > 1 and index % 2 == 0):
podlista = lista[1:-1]
podpodlista = []
for i in podlista:
podpodlista.append(i)
podpodlista.append(i)
podpodlista.append(lista[-1])
podpodlista.insert(0, lista[0])
elif (index > 1 and index % 2 == 1):
podlista = lista[1:-1]
print(len(podlista)/2)
podlista1 = podlista[0:int(len(podlista) / 2)]
podlista2 = podlista[int(len(podlista) / 2):len(podlista)]
podpodlista = []
for i in podlista1:
podpodlista.append(i)
podpodlista.append(i)
podpodlista.append(podlista1[-1])
podpodlista.append(podlista2[0])
for j in podlista2:
podpodlista.append(j)
podpodlista.append(j)
podpodlista.append(lista[-1])
podpodlista.insert(0, lista[0])
if index <= 1:
lis_of_listas.append(lista)
else:
lis_of_listas.append(podpodlista)
index += 1
return [item for sublist in lis_of_listas for item in sublist]
答案 0 :(得分:1)
我们可以看到,对于父行中索引为 j
的每个元素,我们需要在下一行中取出索引为 j
和 j+1
的元素:
例如,要在二叉树中从索引为 ix = [0, 1]
的第 2 行到第 3 行,我们将获取第 2 行中的索引并将它们中的每一个拆分为其子节点 j => [j, j+1]
,使其{ {1}} 在第 3 行。
同样,可以通过将具有相同逻辑的 ix = [0, 1, 1, 2]
拆分为 ix = [0, 1, 1, 2]
,依此类推,从第 3 行计算第 4 行。
基于这些索引数组,我们可以创建一个二叉树:
现在要获得二叉树的实际列表表示,剩下的就是连接索引列表并获取这些索引处的值。
以下是如何在代码中完成此操作:
[0, 1, 1, 2, 1, 2, 2, 3]
输出:
s = \
""" 2
4 9
4 9 6
7 7 8 9"""
# convert string to a list of lists (row, values)
# l = [['2'], ['4', '9'], ['4', '9', '6'], ['7', '7', '8', '9']]
l = [x.split() for x in s.split('\n')]
# init
out = [l[0][0]] # store output here, init with root
ix = [0] # indices of the previous row
# loop
for i in range(len(l)-1):
ix_new = [] # indices for the new row
# if parent has index (j), then
# - left child will have index (j)
# - right child will have index (j+1)
for j in ix:
ix_new.append(j) # left
ix_new.append(j+1) # right
ix = ix_new
# appending elements with corresponding indices to out:
for k in ix_new:
out.append(l[i+1][k])
out
附言对于那些有兴趣从列表格式中获得树的可视化表示的人,请参阅 this question
答案 1 :(得分:0)
这是一个简单的变异方法:
from dataclasses import dataclass
@dataclass
class Node:
value: int
left: object
rite: object
def tree_from_list(l, depth):
l = iter(l)
root = Node(next(l), None, None)
leaves = [root]
for _ in range(depth):
new_leaves = [Node(next(l), None, None)]
for leaf in leaves:
leaf.left = new_leaves[-1]
leaf.rite = Node(next(l), None, None)
new_leaves.append(leaf.rite)
leaves = new_leaves
return root
以上对树的左右分支使用相同的对象,从而节省内存。
用法:
def print_tree(node, indent=''):
if node is None:
return
print(indent + str(node.value))
print_tree(node.left, indent=indent+' ')
print_tree(node.rite, indent=indent+' ')
print_tree(tree_from_list([
1,
2, 3,
4, 5, 6,
], depth=2))
这应该打印:
1
2
4
5
3
6
7
答案 2 :(得分:0)
解决方案比您想象的要容易得多。首先,将您的金字塔视为一个图表,其中级别 l
和索引 i
上的节点与两个节点链接
级别 l + 1
,索引 i
级别 l + 1
,索引 i + 1
现在您以预排序的方式从 0 级的唯一节点开始探索您的图形,您会注意到可以在许多路径上找到相同的节点,这对应于二叉树中的重复条目。例如,要查找节点 8
,有以下路径:
2
/
4 9
\
4 9 6
\
7 7 8 9
2
\
4 9
/
4 9 6
\
7 7 8 9
2
\
4 9
|
4 9 6
|
7 7 8 9
我只是意识到如果我向您展示代码可能会更容易:
pyramid = [(2,), (4,9), (4,9,6), (6,7,8,9), (1,2,3,4,5)]
final_tree = [[] for _ in range(len(pyramid))]
def pyramid_visit(pyramid, cur_lvl, cur_index):
if cur_lvl == len(pyramid):
return
final_tree[cur_lvl].append(pyramid[cur_lvl][cur_index])
pyramid_visit(pyramid, cur_lvl + 1, cur_index)
pyramid_visit(pyramid, cur_lvl + 1, cur_index + 1)
pyramid_visit(pyramid, 0, 0)
print(final_tree)
然后返回:
[[2], [4, 9], [4, 9, 9, 6], [6, 7, 7, 8, 7, 8, 8, 9], [1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5]]
尝试使用 3 层高的金字塔,非常类似于一棵树:
2
/ \
4 9
/ \ / \
4 9 6
接下来添加一个级别,并确定 2 个底层金字塔:
1 1
/ \
2 3 2 3
/ \ / \
4 9 4 4 9 4
/ \ / \ / \ / \
4 9 6 5 4 9 6 5
您应该清楚地看到 2 个子树,这是我的解决方案背后的递归推理。