级别填充的二叉树

时间:2019-06-27 16:03:08

标签: python binary-tree

为了更好地理解递归函数,我试图为插入值的二叉树创建一个Python脚本,完全填充级别,然后再转到下一个树。

这是我的树节点实现:

class Node:
    def __init__(self, value):
        self.value = value
        self.right_child = None
        self.left_child = None
        self.parent = None

class Tree:
    def __init__(self):
        self.root = None

我现在遇到的问题是设置满足该条件的条件。

一个例子:在这里我要按顺序添加以下数字:12、5、18、2、9、15、19、13、17。因此,将东西放到下一层的唯一条件是父母的一个被填补。

  _12_______
 /          \
 5       __18_
/ \     /     \
2 9    15_   19
/   \
13  17

这是我到目前为止所拥有的:

def insert(self,value):
    if(self.root==None):
            self.root=Node(value)
    else:
            self._insert(value,self.root)

def _insert(self, value, curNode):
        if(curNode.left_child==None):
                curNode.left_child=Node(value)
                curNode.left_child.parent = curNode

        elif(curNode.right_child==None):
                curNode.right_child=Node(value)    
                curNode.right_child.parent = curNode    

        else:
                self._insert(value,curNode.left_child)

给出:

          _12_
         /    \
       __5   18
      /   \
    __2_  9
   /    \
  15_  19
 /   \
13  17

因此忽略了所有正确的孩子。当然,问题是我的代码的最后else。如何使它同时考虑节点的左子节点和右子节点?

3 个答案:

答案 0 :(得分:2)

您实际上不需要为此使用左右指针的节点结构。只需将整个树存储在一个数组中,以使索引为N的节点的子节点位于2*N+12*N+2

def print_tree(items, pos, level):
    if pos >= len(items):
        return
    print('.' * level, items[pos])
    print_tree(items, pos * 2 + 1, level + 1)
    print_tree(items, pos * 2 + 2, level + 1)


print_tree([12, 5, 18, 2, 9 , 15, 19, 13, 17], 0, 0)

打印

 12
. 5
.. 2
... 13
... 17
.. 9
. 18
.. 15
.. 19

这就是你想要的。

这称为binary heap

如果您要寻找一棵搜索树(一种保持值顺序的树),并且希望保持平衡,请查看https://en.wikipedia.org/wiki/Self-balancing_binary_search_tree

答案 1 :(得分:0)

georg's answer是代表这一点的聪明方法。但是,如果您对如何使用树结构来获得相同的结果感兴趣,则可以将问题分为两部分:首先找到未完成的最浅节点,然后向其添加新节点。这是一种方法:

class Node:
    def __init__(self, value):
        self.value = value
        self.right_child = None
        self.left_child = None
        self.parent = None

class Tree:
    def __init__(self):
        self.root = None

    def insert(self, value):
        if self.root is None:
            self.root = Node(value)
        else:
            # Find shallowest incomplete node (ignore returned depth)
            node, _ = Tree._next_insertion_node(self.root)
            # Add new node to it
            if node.left_child is None:
                node.left_child = Node(value)
            else:
                node.right_child = Node(value)

    @staticmethod
    def _next_insertion_node(node, level=0):
        # Returns shallowest incomplete node and its depth
        if node.left_child is None or node.right_child is None:
            return node, level
        node_left, level_left = Tree._next_insertion_node(node.left_child, level + 1)
        node_right, level_right = Tree._next_insertion_node(node.right_child, level + 1)
        if level_left <= level_right:
            return node_left, level_left
        else:
            return node_right, level_right

    def print(self):
        Tree._print_node(self.root)

    @staticmethod
    def _print_node(node, level=0):
        if node is None: return
        print(' ' * (level * 2), '*', node.value)
        Tree._print_node(node.left_child, level + 1)
        Tree._print_node(node.right_child, level + 1)

numbers = [12, 5, 18, 2, 9 , 15, 19, 13, 17]
tree = Tree()
for number in numbers:
    tree.insert(number)
tree.print()
# * 12
#   * 5
#     * 2
#       * 13
#       * 17
#     * 9
#   * 18
#     * 15
#     * 19

答案 2 :(得分:0)

不确定这是最好的方法,但是我尝试编写与您尝试的方法类似的方法。我们记录两个节点,然后依次遍历,以便我们看到它们,而不是立即转到左边的节点。所以首先是root,然后是root.left,root.right,root.left.left,root.left.right,root.right.left ...等

class Node:
    def __init__(self, value):
        self.value = value
        self.right_child = None
        self.left_child = None
        self.parent = None

class Tree:
    def __init__(self):
        self.root = None

    # record nodes that need processing.
    nodes_to_process = []

    def insert(self,value):
        if(self.root==None):
            self.root=Node(value)
        else:
            # add the node to be processed
            self.nodes_to_process.append(self.root)
            self._insert(value)

    def _insert(self,value):
        # the current node is the next node in the list.
        curNode = self.nodes_to_process[0]

        if(curNode.left_child==None):
            curNode.left_child=Node(value)
            curNode.left_child.parent = curNode
            # reset the list, since we've inserted.
            self.nodes_to_process = []

        elif(curNode.right_child==None):
            curNode.right_child=Node(value)    
            curNode.right_child.parent = curNode   
            # reset the list, since we've inserted.
            self.nodes_to_process = []

        else:
            # insert the two child nodes.
            self.nodes_to_process.append(curNode.left_child)
            self.nodes_to_process.append(curNode.right_child)
            # Remove the node we've just examined.
            self.nodes_to_process.pop(0)
            self._insert(value)

这是一个快速测试。

tree = Tree()        

for number in [12, 5, 18, 2, 9 , 15, 19, 13, 17]:
    tree.insert(number)

print(tree.root.value) # 12
print(tree.root.left_child.value) #5
print(tree.root.left_child.left_child.value) # 2
print(tree.root.left_child.left_child.left_child.value) # 13
print(tree.root.left_child.left_child.right_child.value) # 17