繁体   English   中英

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

[英]Understanding binary search tree insertion using Python

我试图理解Python中的以下二进制搜索树节点插入实现。 我在insert函数中放了一些print语句。 我可以理解两个插入调用生成的前两个打印但我无法理解在第三次插入调用之前生成的第三个打印。 调试打印的实现如下:

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,如果condition和root获取值10,程序将进入first。这将完成递归调用,程序将执行next print("left: " + str(root.left.value))语句print("left: " + str(root.left.value))打印10.如果条件为false,则程序计算第三个,并完成插入10的函数调用。

  2. insert(root, Node(2))

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

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

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

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

当插入节点2时,它会在第二个if语句中进行两次,如您所说:

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

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

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

我尝试了几个实验,根据结果,以下是一个答案:

当插入函数的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调用insert函数返回驻留在50359600的root 50

50359600

插入第二节点2

left: 2  3.398226880729788e-05

使用return root调用插入函数返回到50359600但通过50360272(id为2的立即根10)并在返回根50之前打印10 @ 50359600

50360272
left: 10  4.8330337859268096e-05
50359600

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

right: 80  6.305598767576385e-05
50359600

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM