二叉 Tree/Search 树
Binary Tree/Search Tree
我开始学习 Python 中的数据结构和算法,我现在正在学习二叉树。但是我真的很困惑如何实施它们。我看到一些实现有两个 classes,一个用于节点,一个用于树本身,如下所示:
class Node:
def __init__(self, data):
self.right = None
self.left = None
self.data = data
class Tree:
def __init__(self):
self.root = None
def insert()
def preorder()
.
.
.
但是我也看到没有节点 class 的实现,而是所有代码都进入树 class 而没有以下
def __init__(self):
self.root = None
谁能帮我理解为什么有两种不同的方法,每种方法的优缺点,它们之间的区别以及我应该遵循哪种方法来实现二叉树。
谢谢!
是的,有这两种方式。
首先,在 1-class 方法中,class 实际上是 2-[= 的 Node
class(可能命名不同) 107=] 方法。没错,所有的方法都在 Node
class 上,但在 2-class 方法中也可能是这种情况,其中 Tree
class 会通过调用 Node
class 上的方法来推迟大部分工作。所以 1-class 方法真正缺少的是 Tree
class。 class 的名称可能会掩盖这一观察,但最好这样看,即使使用树的方法在 Node
class.[=48 上也是如此=]
当您需要表示一棵空树时,差异就变得很明显了。使用 1-class 方法,您必须将主变量设置为 None
。但是 None
与没有节点的树是不同的概念。因为在代表一棵空树的对象上,仍然可以调用方法再次添加节点。您不能在 None
上调用方法。这也意味着调用者需要知道何时将其自己的变量更改为 None
或更改为 Node 实例,具体取决于树是否恰好(或变为)空。
对于 2-class 系统,此管理从调用者手中取出,并在 Tree
实例内部进行管理。调用者将始终使用对该实例的单一引用,与树是否为空无关。
示例
1。创建一个空树
1-class方法:
root = None
2-class 方法:
tree = Tree()
2。将第一个值添加到空树
1-class 方法
# Cannot use an insert method, as there is no instance yet
root = new Node(1) # Must get the value for the root
2-class 方法
tree.insert(1) # No need to be aware of a changing root
由于1-class方法在这种情况下需要获取根的值,你经常看到使用这种方法,根总是被捕获就像那样,即使树不是空的。在那种情况下,调用者的 root
变量的值不会真正改变。
3。从树中删除最后一个值
root = root.delete(1) # Must get the new value for the root; could be None!
2-class 方法
tree.delete(1) # No need to be aware of a changing root
尽管删除通常不会导致空树,但在 1-class 方法中,调用者必须考虑到这种可能性并始终分配给自己的根引用,因为它可能会变成None
.
1-class 系统的变体
1。一个None
值
有时您会看到用具有 None
值的 Node
实例表示空树的方法,以表明这不是真正的数据。然后,当第一个值添加到树中时,该节点的值更新为该值。通过这种方式,调用者不再需要管理根:它总是对同一个 Node
实例的引用,有时它可以有一个 None
值,以表明树实际上是空的.
调用者使用此 1-class 变体的代码将与 2-class 方法相同。
这是不好的做法。在某些情况下,您可能希望一棵树能够将 None
值作为数据,然后您不能创建具有这样值的树,因为它会被误认为是代表空树的虚拟节点
2。哨兵节点
这是上述的变体。这里的虚拟节点 always 在那里。空树由单个节点实例表示。当第一个值被插入到树中时,这个虚拟节点的值永远不会更新,但是插入发生在它的 left
成员上。所以虚拟节点从来没有起到保存数据的作用,而只是在其 left
成员中维护树的真正根的容器。这实际上意味着虚拟节点与 2-class 方法中的 Tree
实例平行。它没有适当的 root
成员,而是具有该角色的 left
成员,并且它的 right
成员没有用处。
本机数据结构是如何实现的
2-class 方法更像是本机数据类型的工作方式。例如,以 Python 中的标准 list
为例。空列表由 []
表示,而不是 None
。 []
和 None
之间有明显的区别。一旦获得列表引用(如 lst = []
),该引用就永远不会改变。您可以追加和删除,但您永远不必 将 分配给 lst
本身。
我开始学习 Python 中的数据结构和算法,我现在正在学习二叉树。但是我真的很困惑如何实施它们。我看到一些实现有两个 classes,一个用于节点,一个用于树本身,如下所示:
class Node:
def __init__(self, data):
self.right = None
self.left = None
self.data = data
class Tree:
def __init__(self):
self.root = None
def insert()
def preorder()
.
.
.
但是我也看到没有节点 class 的实现,而是所有代码都进入树 class 而没有以下
def __init__(self):
self.root = None
谁能帮我理解为什么有两种不同的方法,每种方法的优缺点,它们之间的区别以及我应该遵循哪种方法来实现二叉树。
谢谢!
是的,有这两种方式。
首先,在 1-class 方法中,class 实际上是 2-[= 的 Node
class(可能命名不同) 107=] 方法。没错,所有的方法都在 Node
class 上,但在 2-class 方法中也可能是这种情况,其中 Tree
class 会通过调用 Node
class 上的方法来推迟大部分工作。所以 1-class 方法真正缺少的是 Tree
class。 class 的名称可能会掩盖这一观察,但最好这样看,即使使用树的方法在 Node
class.[=48 上也是如此=]
当您需要表示一棵空树时,差异就变得很明显了。使用 1-class 方法,您必须将主变量设置为 None
。但是 None
与没有节点的树是不同的概念。因为在代表一棵空树的对象上,仍然可以调用方法再次添加节点。您不能在 None
上调用方法。这也意味着调用者需要知道何时将其自己的变量更改为 None
或更改为 Node 实例,具体取决于树是否恰好(或变为)空。
对于 2-class 系统,此管理从调用者手中取出,并在 Tree
实例内部进行管理。调用者将始终使用对该实例的单一引用,与树是否为空无关。
示例
1。创建一个空树
1-class方法:
root = None
2-class 方法:
tree = Tree()
2。将第一个值添加到空树
1-class 方法
# Cannot use an insert method, as there is no instance yet
root = new Node(1) # Must get the value for the root
2-class 方法
tree.insert(1) # No need to be aware of a changing root
由于1-class方法在这种情况下需要获取根的值,你经常看到使用这种方法,根总是被捕获就像那样,即使树不是空的。在那种情况下,调用者的 root
变量的值不会真正改变。
3。从树中删除最后一个值
root = root.delete(1) # Must get the new value for the root; could be None!
2-class 方法
tree.delete(1) # No need to be aware of a changing root
尽管删除通常不会导致空树,但在 1-class 方法中,调用者必须考虑到这种可能性并始终分配给自己的根引用,因为它可能会变成None
.
1-class 系统的变体
1。一个None
值
有时您会看到用具有 None
值的 Node
实例表示空树的方法,以表明这不是真正的数据。然后,当第一个值添加到树中时,该节点的值更新为该值。通过这种方式,调用者不再需要管理根:它总是对同一个 Node
实例的引用,有时它可以有一个 None
值,以表明树实际上是空的.
调用者使用此 1-class 变体的代码将与 2-class 方法相同。
这是不好的做法。在某些情况下,您可能希望一棵树能够将 None
值作为数据,然后您不能创建具有这样值的树,因为它会被误认为是代表空树的虚拟节点
2。哨兵节点
这是上述的变体。这里的虚拟节点 always 在那里。空树由单个节点实例表示。当第一个值被插入到树中时,这个虚拟节点的值永远不会更新,但是插入发生在它的 left
成员上。所以虚拟节点从来没有起到保存数据的作用,而只是在其 left
成员中维护树的真正根的容器。这实际上意味着虚拟节点与 2-class 方法中的 Tree
实例平行。它没有适当的 root
成员,而是具有该角色的 left
成员,并且它的 right
成员没有用处。
本机数据结构是如何实现的
2-class 方法更像是本机数据类型的工作方式。例如,以 Python 中的标准 list
为例。空列表由 []
表示,而不是 None
。 []
和 None
之间有明显的区别。一旦获得列表引用(如 lst = []
),该引用就永远不会改变。您可以追加和删除,但您永远不必 将 分配给 lst
本身。