【问题标题】:How to convert a pyramid into a binary tree如何将金字塔转换为二叉树
【发布时间】:2021-03-14 21:39:09
【问题描述】:

假设我有一个像这样的金字塔,但更大

     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]

【问题讨论】:

  • 您能否详细说明当您说“要将其转换为列表以便单独处理每个节点”时的意思?您是如何从示例树获得所需的输出的?
  • 这甚至不是您展示的二叉树。中间的 9 应该是上面 4 的右孩子,上面 9 的左孩子,还是两者兼而有之?所需输出中的三个额外值是从哪里来的?
  • 我编辑了我的问题,其实你是对的@jasonharper,我想把它转换成二叉树

标签: python binary-tree


【解决方案1】:

我们可以看到,对于父行中索引为j的每个元素,我们需要在下一行中获取索引为jj+1的元素:

例如,从索引为ix = [0, 1] 的第2 行转到二叉树中的第3 行,我们将获取第2 行中的索引并将它们中的每一个拆分为其子j =&gt; [j, j+1],使其成为ix = [0, 1, 1, 2] 在行中3.

同样,第 4 行可以通过将 ix = [0, 1, 1, 2] 以相同逻辑拆分为 [0, 1, 1, 2, 1, 2, 2, 3] 等从第 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

输出:

['2', '4', '9', '4', '9', '9', '6', '7', '7', '7', '8', '7', '8', '8', '9']

附:对于那些有兴趣从列表格式中获得树的可视化表示的人,请参阅this question

【讨论】:

  • 那是……不是二叉树?
  • @user3840170 这是二叉树的标准列表表示,我认为这是 OP 想要实现的。也许我没看懂你的意思?
  • 这就是我想要实现的。抱歉,如果有人误解了我的问题。
【解决方案2】:

解决方案比您想象的要容易得多。首先,将您的金字塔想象成一个图形,其中级别 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 个子树,这是我的解决方案背后的递归推理。

【讨论】:

    【解决方案3】:

    这里有一个简单的变异方法:

    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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-02-28
      • 1970-01-01
      • 2021-06-07
      • 2018-12-29
      • 2020-08-24
      • 1970-01-01
      • 2015-11-09
      • 2015-09-24
      相关资源
      最近更新 更多