一、Python中树的定义:一棵树由根和其他子树组成,这些子树也是树。
二、python中树的实现:
1、python中可以用列表表示树,列表中有三个元素[根,左孩子,右孩子],左右孩子还是一个列表,也是由三个元素组成。
例如['a', ['b', 'c', []], []]:这棵数根节点是'a',左孩子是['b', 'c', []],右孩子是[],左孩子也是一棵树,树根为'b',左孩子是'c',右孩子是[]。
def binary_tree(root):
"""创建一个新树,root为根节点"""
return [root, [], []]
def insert_left(root, new_branch):
""" 插入左子树,new_branch左子树的根节点。
如果原来的树没有左子树,则直接插入根节点;
如果原来的树存在左子树,则原来的子树会变成新子树的左节点
"""
t = root.pop(1)
if len(t) > 1: # 存在原来的左子树
root.insert(1, [new_branch, t, []])
else:
root.insert(1, [new_branch, [], []])
return root
def insert_right(root, new_branch):
""" 插入右子树,new_branch右子树的根节点。
如果原来的树没有右子树,则直接插入根节点;
如果原来的树存在右子树,则原来的子树会变成新子树的右节点
"""
t = root.pop(2)
if len(t) > 1: # 存在原来的右子树
root.insert(2, [new_branch, [], t])
else:
root.insert(2, [new_branch, [], []])
return root
def get_root_val(root):
"""返回根节点的值"""
return root[0]
def set_root_val(root, new_val):
"""修改根节点的值"""
root[0] = new_val
def get_left_child(root):
"""返回左子树列表"""
return root[1]
def get_right_child(root):
"""返回右子树列表"""
return root[2]
# 测试
tree = binary_tree('a')
insert_left(tree, 'b')
insert_right(tree, 'c')
insert_right(get_right_child(tree), 'd')
insert_left(get_right_child(tree), 'e')
print(tree)
2、python中还可以用Nodes and References表示树,这种思想一般通过定义类来实现:
class BinaryTree:
"""通过类来实现树"""
def __init__(self, root):
"""初始化树,root为根节点"""
self.key = root
self.left_child = None
self.right_child = None
def insert_left(self, new_node):
""" 插入左子树:new_node为左子树的根节点
如果原来的树不存在左子树,则new_node成为root树的左子树
如果原来的树存在左子树,则原来的左子树变为以new_node为根节点的左子树
"""
if self.left_child:
t = BinaryTree(new_node)
t.left_child = self.left_child
self.left_child = t
else:
self.left_child = BinaryTree(new_node)
def insert_right(self, new_node):
""" 插入右子树:new_node为右子树的根节点
如果原来的树不存在右子树,则new_node成为root树的右子树
如果原来的树存在右子树,则原来的右子树变为以new_node为根节点的右子树
"""
if self.right_child:
t = BinaryTree(new_node)
t.right_child = self.right_child
self.right_child = t
else:
self.right_child = BinaryTree(new_node)
def get_right_child(self):
"""得到root树的右子树"""
return self.right_child
def get_left_child(self):
"""得到root树的左子树"""
return self.left_child
def set_root_val(self,obj):
"""修改root树的根节点的值"""
self.key = obj
def get_root_val(self):
"""得到root树的根节点的值"""
return self.key
# 测试
tree = BinaryTree('a')
tree.insert_left('b')
tree.insert_right('c')
tree.get_right_child().insert_right('f')
print(tree)
三、树的遍历
树的遍历分为三种:先序遍历,中序遍历,后序遍历
先序遍历(preorder,根左右)
def preorder(tree):
if tree:
print(tree.get_root_val())
preorder(tree.get_left_child())
preorder(tree.get_right_child())
中序遍历(inorder,左根右),
def inorder(tree):
if tree:
inorder(tree.get_left_child())
print(tree.get_root_val)
inorder(tree.get_right_child())
后序遍历(postorder,左右根)
def postorder(tree):
if tree:
postorder(tree.get_left_child())
postorder(tree.get_right_child())
print(tree.get_root_val)
四、二叉搜索树
二叉搜索树有一个重要的特性:parent的key值比左结点大,比右结点小。
# 二叉搜索树 BST
class TreeNode:
"""BST的结点类"""
def __init__(self, value, left=None, right=None):
"""初始化结点"""
self.value = value
self.left_child = left
self.right_child = right
class BST:
"""二叉搜索树的类"""
def __init__(self):
"""初始化BST,root树为空"""
self.root = None
def insert(self, value, root):
"""插入结点"""
if not root: # 该节点为根节点
root = TreeNode(value)
elif value < root.value:
root.left_child = self.insert(value, root.left_child)
elif value > root.value:
root.right_child = self.insert(value, root.right_child)
return root
def delete(self, root, value):
"""
删除二叉搜索树中值为value的点:
若找到,则删除,返回该节点;
若没找到,则返回False
"""
if root:
if value < root.value:
root.left_child = self.delete(root.left_child, value)
elif value > root.value:
root.right_child = self.delete(root.right_child, value)
# 当value == root.value时,分为三种情况:只有左子树或者只有右子树、有左右子树、即无左子树又无右子树
else:
if root.left_child and root.right_child:
# 既有左子树又有右子树,则需找到右子树中最小值节点
temp = self.findMin(root.right_child)
root.value = temp.value
# 再把右子树中最小值节点删除
root.right_child = self.delete(root.right_child, temp.value)
elif root.right_child:
# 只有右子树
root = root.right_child
elif root.left_child:
# 只有左子树
root = root.left_child
else:
# 左右子树都为空
root = None
return root
else:
return False
def inorder(self, root):
"""中序遍历BST"""
if root:
self.inorder(root.left_child)
print(root.value, end=' ')
self.inorder(root.right_child)
else:
print(None, end='')
def depth(self, root):
"""返回树的深度"""
if root:
return 1 + max(self.depth(root.left_child), self.depth(root.right_child))
else:
return 0
def search(self, value, root):
""" 二叉搜索树查询操作:
if not root:
root = self.root
根据所给的value,查询树中是否存在。
如存在,则返回该结点;若不存在,则返回False
"""
if not root:
return False
if root.value == value:
return root
elif value < root.value:
return self.search(value, root.left_child)
elif value > root.value:
return self.search(value, root.right_child)
def findMin(self, root):
"""
查找二叉搜索树中最小值
返回最小值结点
"""
if root.left_child:
return self.findMin(root.left_child)
else:
return root
def findMax(self, root):
"""
查找二叉搜索树中最大值
返回最大值结点
"""
if root.right_child:
return self.findMax(root.right_child)
else:
return root
def main():
"""测试BST"""
root = BST()
root.root = root.insert(7, root.root)
root.root = root.insert(4, root.root)
root.root = root.insert(5, root.root)
root.root = root.insert(10, root.root)
root.root = root.insert(9, root.root)
root.root = root.insert(13, root.root)
root.root = root.insert(12, root.root)
root.inorder(root.root)
print('深度:', root.depth(root.root))
print('最大值:', root.findMax(root.root).value)
print('最小值:', root.findMin(root.root).value)
print('搜索:', root.search(8, root.root))
print('搜索:', root.search(12, root.root).value)
print('delete')
topo = """
7
4 10
5 9 13
12
测试的时候建议先画好删除以后的图,然后对照着图和结果检查
"""
print('树图', topo)
root.root = root.delete(root.root, 6) # 找不到
root.inorder(root.root)
print()
root.root = root.delete(root.root, 9) # 左右子女都没有
root.inorder(root.root)
print()
root.root = root.delete(root.root, 13) # 只有左子女
root.inorder(root.root)
print()
root.root = root.delete(root.root, 4) # 只有右子女
root.inorder(root.root)
print()
root.root = root.delete(root.root, 7) # 左右子女都有
root.inorder(root.root)
if __name__ == "__main__":
main()