在Python中,将一个整数列表转换成二叉树。

huangapple go评论73阅读模式
英文:

In Python, convert a list of integers into a binary tree

问题

我有一个整数列表,我想在Python中将其转换为二叉树。每个元素应该放在树中的下一个可用位置,从左到右进行。

例如,整数列表可以是

root = [3, 9, 20, None, None, 15, 7]

如果一个节点为None,那么在考虑将列表元素放在哪里时,我希望忽略该节点。因此,对于列表

root = [2, None, 3, None, 4, None, 5, None, 6]

每个元素都在自己的级别上。(这种二叉树的数组表示来自Leetcode的示例(https://leetcode.com/problems/minimum-depth-of-binary-tree/)。

当列表是详尽无遗的,即树中的每个位置都有指定时,我可以解决这个问题;请参考下面的代码:

class Node:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

def array_to_binary_tree(array):
    n = len(array)
    node = Node(array[0])
    nodes = []
    nodes.append(node)
    for i in range(0, n):
        left_index = i * 2 + 1
        if left_index < n:
            node_left = Node(array[left_index])
            nodes.append(node_left)
            nodes[i].left = node_left
        right_index = i * 2 + 2
        if right_index < n:
            node_right = Node(array[right_index])
            nodes.append(node_right)
            nodes[i].right = node_right
    root = nodes[0]
    return root

但是对于给定极简的数组表示,我无法解决这个问题。

英文:

I have a list of integers that I want to convert into a binary tree, in Python. Each element should go to the next available position in the tree, going from left to right.

For example, the list of integers could be

root = [3,9,20,None,None,15,7]

If a node is None, then I want that node to be ignored when considering where to put a list element. So for the list

root = [2,None,3,None,4,None,5,None,6]

each element goes on its own level. (This array representation of binary trees come from Leetcode eg (https://leetcode.com/problems/minimum-depth-of-binary-tree/).)

I can solve the problem when the list is exhaustive, ie each position in the tree is specified, even if it's parent(s) are None; see below.

class Node:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

def array_to_binary_tree(array):
    n = len(array)
    node = Node(array[0])
    nodes = []
    nodes.append(node)
    for i in range(0, n):
        left_index = i * 2 + 1
        if left_index &lt; n:
            node_left = Node(array[left_index])
            nodes.append(node_left)
            nodes[i].left = node_left
        right_index = i * 2 + 2
        if right_index &lt; n:
            node_right = Node(array[right_index])
            nodes.append(node_right)
            nodes[i].right = node_right
    root = nodes[0]
    return root

But I can't solve it for when the array is giving a minimalist representation.

答案1

得分: 1

你的代码似乎假定输入的树是一个完全二叉树,因为你使用了 i * 2 + 1 的公式。但是在示例中表示的树并不是一个完全二叉树,所以这个公式不会起作用。

这里是一个你可以使用的函数:

from collections import deque

def array_to_binary_tree(lst):
    if not lst:
        return
    values = iter(lst)
    root = Node(next(values))
    queue = deque([root])
    while queue:
        node = queue.popleft()
        if node:
            # 从输入列表中获取下两个值,如果它们不是None,则为它们创建一个节点
            children = [
                None if value is None else Node(value)
                for value in (next(values, None), next(values, None))
            ]
            # 将这两个节点添加到队列中,并在树中附加它们
            queue.extend(children)
            node.left, node.right = children

    return root

这里是一个替代方案,不显式调用 iter,而是使用 for 从输入列表中迭代值:

def array_to_binary_tree(lst):
    if not lst:
        return
    node = root = Node(lst[0])
    queue = deque()
    for i, value in enumerate(lst[1:]):
        if value is not None:  # 需要创建一个节点吗?
            queue.append(Node(value))
            if i % 2:  # 在奇数迭代中将其附加为右子节点
                node.right = queue[-1]
            else:  # 在偶数迭代中将其附加为左子节点
                node.left = queue[-1]
        if i % 2 and queue:  # 在奇数迭代后,我们获取下一个父节点
            node = queue.popleft()

    return root
英文:

Your code seems to assume the input tree is a complete binary tree, as you use the i * 2 + 1 formula. But the tree represented in the example is not a complete one, and so that formula is not going to work.

Here is a function you could use:

from collections import deque

def array_to_binary_tree(lst):
    if not lst:
        return
    values = iter(lst)
    root = Node(next(values))
    queue = deque([root])
    while queue:
        node = queue.popleft()
        if node:
            # Get next two values from input list, and 
            #   if they are not None, create a node for them
            children = [
                None if value is None else Node(value)
                for value in (next(values, None), next(values, None))
            ]
            # Append these two to the queue, and also attach them in the tree
            queue.extend(children)
            node.left, node.right = children

    return root

Here is an alternative that doesn't call iter explicitly, but uses for to iterate the values from the input list:

def array_to_binary_tree(lst):
    if not lst:
        return
    node = root = Node(lst[0])
    queue = deque()
    for i, value in enumerate(lst[1:]):
        if value is not None:  # A node to create?
            queue.append(Node(value))
            if i % 2:  # At odd iterations we attach it as a right child
                node.right = queue[-1]
            else:  # At even iterations we attach it as a left child
                node.left = queue[-1]
        if i % 2 and queue:  # After odd iterations we grab a next parent
            node = queue.popleft()

    return root

答案2

得分: 0

这种列表中的树形结构是二叉堆树。给定索引 i 的子节点分别位于 i*2+1i*2+2,左子节点和右子节点分别位于 (i-1)//2 处的父节点。

这应该允许您按顺序处理它们,将列表中的每个值替换为相应的节点:

root = [2,None,3,None,4,None,5,None,6]

root[0] = Node(root[0])
for i,n in enumerate(root):
    if n is None: continue
    root[i] = Node(n)
    if i%2:
        root[(i-1)//2].left  = root[i]
    else:
        root[(i-1)//2].right = root[i]
英文:

This form of tree in a list is a binary heap tree. Children of a given index i are at i*2+1 and i*2+2 for left and right respectively and parents are at (i-1)//2.

This should allow you to process them sequentially, replacing each value in the list by the corresponding node:

root = [2,None,3,None,4,None,5,None,6]

root[0] = Node(root[0])
for i,n in enumerate(root):
    if n is None: continue
    root[i] = Node(n)
    if i%2:
        root[(i-1)//2].left  = root[i]
    else:
        root[(i-1)//2].right = root[i]

huangapple
  • 本文由 发表于 2023年7月10日 18:11:52
  • 转载请务必保留本文链接:https://go.coder-hub.com/76652740.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定