一、树
1. 小结
2. 树的术语
3. 树的种类
4. 二叉树
5. 二叉树的存储
- 顺序存储
- 链式存储
- 完全二叉树适用于顺序存储,不完全二叉树适用于链式存储
6. 树的应用场景
- xml、html
- 路由协议
- mysql的索引(二叉搜索树)
- 文件系统目录结构
- 机器学习经典算法——决策树等
7. 二叉树的性质
8. 完全二叉树的代码实现
import queue
class BinaryTree():
def __init__(self, val):
self.val = val
self.lnode = None
self.rnode = None
class BinaryTree():
def __init__(self, node=None):
self.root = node
def add(self, item):
que = queue.Queue()
if not self.root:
self.root = item
return
que.put(self.root)
while True:
cur = que.get()
if not cur.lnode:
cur.lnode = item
return
else:
que.put(cur.lnode)
if not cur.rnode:
cur.rnode = item
return
else:
que.put(cur.rnode)
# 广度优先遍历,参考下方
def bfs(self):
pass
# 深度优先遍历,参考下方
def dfs(self):
pass
if __name__ == '__main__':
a = BinaryNode(1)
b = BinaryNode(2)
c = BinaryNode(3)
d = BinaryNode(4)
e = BinaryNode(5)
f = BinaryNode(6)
g = BinaryNode(7)
tree = BinaryTree()
tree.add(a)
tree.add(b)
tree.add(c)
tree.add(d)
tree.add(e)
tree.add(f)
tree.add(g)
tree.bfs()
二、树的遍历
1. 广度优先(BFS)
# 采用队列先进先出的思想,将节点依次入队
def bfs(self):
if not self.root:
return
que = queue.Queue()
que.put(self.root)
while not que.empty():
cur = que.get()
print(cur.val)
if cur.lnode:
que.put(cur.lnode)
if cur.rnode:
que.put(cur.rnode)
2. 深度优先(DFS)
1. 三种深度优先遍历
2. 代码实现
# 深度优先 —— 前序遍历
def pre_dfs(self, root):
if root:
print(root.val)
self.pre_dfs(root.lnode)
self.pre_dfs(root.rnode)
# 深度优先 —— 中序遍历
def in_dfs(self, root):
if root:
self.in_dfs(root.lnode)
print(root.val)
self.in_dfs(root.rnode)
# 深度优先 —— 后序遍历
def after_dfs(self, root):
if root:
self.after_dfs(root.lnode)
self.after_dfs(root.rnode)
print(root.val)
3. 根据遍历结果反推二叉树结构
三、树的变种
1. 红黑树
1. 定义
- 二叉查找树(BST):又叫二叉排序树,二叉搜索树,时间复杂度为O(logn),它有以下特点:
- 红黑树本质是一颗特殊的二叉查找树(自平衡的BST),它的优势是:防止BST退化成链表而导致查询效率下降到O(n);
- 红黑树的性质:
- 1.每个节点或是红色的,或是黑色的。
- 2.根节点是黑色的。
- 3.每个叶节点(NIL)是黑色的。
- 4.如果一个节点是红色的,则它的俩个字节点都是黑色的。
- 5.对每个节点,从该节点到其他所有后代叶节点的简单路径上,均包含相同数目的黑色节点。
2. 图示
3. 构建红黑树
todo
4. 如何处理冲突
插入节点后,为了满足红黑树的性质,使用以下规则处理冲突(即不满足红黑树规则的地方):
- 变颜色:红变黑,黑变红
- 左旋:
- 右旋:
5. 编码实现
2. B树、B+树
1. hashmap和红黑树的局限
- 为什么不使用hashmap来实现mysql的索引?
- 因为hash函数会计算一个函数值,hash(userid)=key,userid变化了,key也会变化;
- 联合索引:hash(userid+name)=key=》如果只传了userid不能支持部分索引查询以及范围查找;
- 红黑树为什么不适合mysql的索引?
- 二叉树层数太深,读取磁盘次数过多
- 磁盘1页有16K,只存单个节点数据浪费空间
2. B-tree定义
- b-tree图示
- 性质:
3. B+tree定义
- b+tree图示
- 性质:
4. 构建B+tree
分裂,todo
5. B+tree的优点
- B+的磁盘读写代价更低
B+的内部结点并没有指向关键字具体信息的指针。因此其内部结点相对B树更小。如果把所有同一内部结点的关键字存放在同一盘块中,那么盘块所能容纳的关键字数量也越多。一次性读入内存中的需要查找的关键字也就越多。相对来说IO读写次数也就降低了。
- B+tree的查询效率更加稳定
由于非终结点并不是最终指向文件内容的结点,而只是叶子结点中关键字的索引。所以任何关键字的查找必须走一条从根结点到叶子结点的路。所有关键字查询的路径长度相同,导致每一个数据的查询效率相当。
3. 哈夫曼树
1. 定义
- 当用 n 个结点(都做叶子结点且都有各自的权值)试图构建一棵树时,如果构建的这棵树的带权路径长度最小,称这棵树为“最优二叉树”,有时也叫“赫夫曼树”或者“哈夫曼树”。
- 相关概念:
2. 图示
3. 应用
- 哈夫曼编码: 哈夫曼树的应用很广,哈夫曼编码就是其在电讯通信中的应用之一。广泛地用于数据文件压缩的十分有效的编码方法。其压缩率通常在20%~90%之间。