树的实例:模拟文件系统
class Node:
def __init__(self, name, type='dir'):
self.name = name
self.type = type #'dir' or 'file'
self.children = []
self.parent = None
def __repr__(self):
return self.name
n = Node('Hello')
m = Node('world')
n.children.append(m)
m.parent = n
class FileSystemTree:
def __init__(self):
self.root = Node("/")
self.now = self.root
def mkdir(self, name): #创建文件夹,name以/结尾
if name[-1] == '/':
name += '/'
node = Node(name)
self.now.children.append(node)
node.parent = self.now
def ls(self): #列出目录内容
return self.now.children
def cd(self, name):
if name[-1] == '/':
name += '/'
if name == '../':
self.now = self.now.parent
return
for child in self.now.children:
if child.name = name:
self.now = child
return
raise ValueError('invalid dir')
二叉树
- 二叉树的链式存储:将二叉树的节点定义为一个对象,节点之间通过类似链表的链接方式来连接
代码:
def BiTreeNode:
def __init__(self, data):
self.data = data
self.lchild = None #左孩子
self.rchild = None #右孩子
二叉树的遍历
- 前序遍历:EACBDGF
- 中序遍历:ABCDEGF
- 后续遍历:BDCAFGE
- 层次遍历:EAGCFBD
代码:
def pre_order(root): #前序
if root:
print(root.data, end=',')
pre_order(root.lchild)
pre_order(root.rchild)
def in_order(root): #中序
if root:
in_order(root.lchild)
print(root.data, end=',')
in_order(root.rchild)
def post_order(root): #后序
if root:
post_order(root.lchild)
post_order(root.rchild)
print(root.data, end=',')
from collections import deque
def level_order: #层次
queue = deque()
queue.append(root):
while len(queue) > 0: #只要队不空
node = queue.popleft()
print(node.data, end=',')
if node.lchild:
queue.append(node.lchild)
if node.rchild:
queue.append(node.rchild)
二叉搜索树
- 二叉搜索树是一颗二叉树且满足性质:设x是二叉树的一个节点。如果y是x左子树的一个节点,那么y.key≤x.key;如果y是x右子树的一个节点,那么y.key≥x.key
- 二叉搜索树的操作:查询、插入、删除
- 对于二叉搜索树来说,中序遍历一定是有序的
- 删除操作:
- 如果节点是叶子节点,直接删除
- 如果节点只有一个孩子,将此节点的父亲与孩子连接,然后删除该节点
- 如果节点有两个孩子,将其右子树的最小节点(该节点最多有一个右孩子)删除,并替换当前节点
代码:
def BiTreeNode:
def __init__(self, data):
self.data = data
self.lchild = None #左孩子
self.rchild = None #右孩子
self.parent = None
class BST: #二叉搜索树
def __init__(self, li=None):
self.root = None
if li:
for val inli:
self.insert_no_rec(val)
def query(self,val): #递归实现查询
if not node:
return None
if node.data < val:
return self.query(node.rchild, val)
elif node.data > val:
return self.query(node.lchild, val)
else:
return None
def query_no_rec(self, val): #非递归实现查询
p = self.root
while p:
if p.data < val:
p = p.rchild
elif p.data > val:
p = p.lchild
else:
return p
return None
def insert(self, node, val): #递归实现插入
if not node:
node = BiTreeNode(val)
elif val < node.data:
node.lchild = self.insert(node.lchild, val)
node.lchild.parent = node
elif val > node.data:
node.rchild = self.insert(node.rchild, val)
node.rchild.parent = node
return node
def insert_no_rec(self, val): #非递归实现插入
p = self.root
if not p: #空树
self.root = BiTreeNode(val)
return
while True:
if val < p.data:
if p.lchild:
p = p.lchild
else:
p.lchild = BiTreeNode(val)
p.lchild.parent = p
return
elif val > p.data:
if p.rchild:
p = p.rchild
else:
p.rchild = BiTreeNode(val)
p.rchild.parent = p
return
else:
return
def __remove_node_1(self, node): #情况1:node是叶子节点
if not node.parent:
self.root = None
if node == node.parent.lchild: #如果node是它父亲的左孩子
node.parent.lchild = None
else: #如果node是右父亲的左孩子
node.parent.rchild = None
def __remove_node_21(self, node): #情况2.1:node只有一个左孩子
if not node.parent: #如果是根节点
self.root = node.lchild
node.lchild.parent = None
elif node == node.parent.lchild:
node.parent.lchild = node.lchild
node.lchild.parent = node.parent
else:
node.parent.rchild = node.lchild
node.lchild.parent = node.parent
def __remove_node_22(self, node): #情况2.1:node只有一个右孩子
if not node.parent: #如果是根节点
self.root = node.rchild
node.rchild.parent = None
elif node == node.parent.lchild:
node.parent.lchild = node.rchild
node.rchild.parent = node.parent
else:
node.parent.rchild = node.rchild
node.rchild.parent = node.parent
def delete(self, val):
if self.root: #不是空树
node = self.query_no_rec(val)
if not node: #不存在
return False
if not node.lchild and not node.rchild: #没有左孩子和右孩子
self.__remove_node_1(node)
elif not node.rchild: #只有左孩子
self.__remove_node_21(node)
elif not node.lchild: #只有右孩子
self.__remove_node_22(node)
else: #两个孩子都有
min_node = node.rchild #找右子树最小节点
while min_node.lchild:
min_node = min_node.lchild
node.data = min_node.data
#删除min_node
if min_node.rchild:
self.__remove_node_22(min_node)
else:
self.__remove_node_1(min_node)
二叉搜索树的效率
- 平均情况下,二叉搜索树进行搜索的时间复杂度为O(logn)
- 最坏情况下,二叉搜索树可能非常偏斜
- 解决方案
- 随机化插入
- AVL树
二叉搜索树扩展应用——B树
- B-Tree是一棵自平衡的多路搜索树。常用于数据库的索引。