使用Python了解二进制搜索树插入

时间:2018-07-21 22:56:44

标签: python binary-search-tree

我试图了解以下Python中的二进制搜索树节点插入实现。我在插入函数中放置了一些打印语句。我可以理解由两个插入调用生成的前两个打印,但我不明白在第三个插入调用之前生成的第三个打印。调试打印的实现如下所示:

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


def insert(root, node):
    if root is None:
        root = node
        return root
    if node.value < root.value:
        root.left = insert(root.left, node)
        print("left: " + str(root.left.value))
    if node.value > root.value:
        root.right = insert(root.right, node)
        print("right: " + str(root.right.value))
    return root


root = Node(50)

insert(root, Node(10))
insert(root, Node(2))
insert(root, Node(80))
insert(root, Node(15))
insert(root, Node(60))
insert(root, Node(90))

代码显示:

left: 10
left: 2
left: 10
right: 80
right: 15
left: 10
left: 60

right: 80
right: 90
right: 80

到目前为止,我的理解是

  1. insert(root, Node(10))

    (i)__init__的值为10。由于root已经设置为50,因此如果条件为10 <50,程序将进入第二秒。

    (ii)以root.left为None且节点值为10的方式调用递归插入函数。由于root.left现在为None,因此如果条件和root的值为10,则程序首先进入。这将完成递归调用,并程序将执行下一条语句print("left: " + str(root.left.value)),该语句将打印10。如果条件为false,程序将计算第三条语句,并完成插入10的函数调用。

  2. insert(root, Node(2))

    (i)__init__,其值为value = 2。如果条件为2 <50,则程序进入第二秒。

    (ii)以root.left为10且节点值为2的方式调用递归插入函数。如果条件为2 <10,则程序再次进入第二。

    (iii)递归插入函数被再次调用,root.left为None,值为2。现在,如果条件和root得到,程序首先进入 值2。这将完成递归重复调用,程序将执行下一个打印语句print("left: " + str(root.left.value)),该语句将打印2。

    (iv)现在,按预期的程序将在条件为false的情况下评估第三个并成功调用return。
    但是,在开始insert(root, Node(80))之前,如果条件成立,它将再次返回第二个print语句并打印10。
    我没有得到这个,那为什么在完成(或者不是?)函数调用之后又回到打印语句呢?

2 个答案:

答案 0 :(得分:2)

插入节点2时,它将两次进入第二个if语句,如您所说:

insert(root, Node(2)) -> root being Node 50
insert(root, Node(2)) -> root being Node 10

因此,当递归步骤结束时,将运行两个打印语句,但顺序相反。这意味着第一张照片将显示节点10的左侧(已插入节点2),第二张照片将显示节点50的左侧(节点10)

您可以将上面的代码可视化为堆栈,因此所有操作都需要在算法完成之前执行,并且顶部的内容将首先执行。

答案 1 :(得分:1)

我尝试了一些实验,并根据结果进行了回答:

当插入函数的return root通过中间节点到达根节点时,将对被注入2层或更多层的节点执行附加打印。将代码与其他调试打印一起发布,以跟踪根对象的ID和打印执行的时间戳。

代码:

import time


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


def insert(root, node):
    if root is None:
        root = node
        return root
    if node.value < root.value:
        root.left = insert(root.left, node)
        print("left: " + str(root.left.value) + "  " + str(time.clock()))
    if node.value > root.value:
        root.right = insert(root.right, node)
        print("right: " + str(root.right.value) + "  " + str(time.clock()))
    print(id(root))
    return root


root = Node(50)
print("root node id: " + str(id(root)))

insert(root, Node(10))
insert(root, Node(2))
insert(root, Node(80))
insert(root, Node(15))
insert(root, Node(60))
insert(root, Node(90))

带有内联注释的程序输出:

为根节点50分配了对象ID 50359600

 root node id: 50359600 

已插入第一个节点10

left: 10  3.77580764525532e-07

通过return root调用插入函数,返回根50驻留在50359600上

50359600

插入了第二个节点2

left: 2  3.398226880729788e-05

使用return root调用插入函数可通过50360272(2的直接根10的ID)返回50359600,并在返回根50 @ 50359600之前打印10。

50360272
left: 10  4.8330337859268096e-05
50359600

80是紧接在右侧50之后的右侧节点,因此return root在注入80之后直接达到50 @ 50359600。

right: 80  6.305598767576385e-05
50359600

类似于之前执行的节点2,在插入15个插入函数之后,必须通过10的return root调用返回到50。

right: 15  7.702647596320853e-05
50360272
left: 10  8.986422195707663e-05
50359600

同样。...

left: 60  0.00010345712947999577
50360304
right: 80  0.0001155397139448128
50359600

right: 90  0.00012837745993868089
50360304
right: 80  0.00014008246363897238
50359600