常用树的数据结构总结

二叉搜索树: 满足左孩子<根<右孩子,递归定义。中序遍历是有序的,主要是为了快速搜索logn;

AVL:平衡二叉搜索树。任意节点左右子树高度不超过1。主要是防止二叉树退化成链表导致性能降到O(n);

红黑树:一种自平衡的二叉查找树。因为AVL为了保证高度差异和严格一致性,插入数据必须调整树的结构,这个调整次数可能会很多,影响性能;红黑树可以实现3次旋转就能找到,也就是它放弃了绝对一致性保证插入的高效。(应用于插入删除查找很频繁的场景)在很多场景都用到了红黑树,比如stl的map,比如linux内核中任务结构体里面任务的调度,就会根据虚拟运行时间来挂载到红黑树上,快速查找进行调度;内核中虚拟地址空间的各个部分也用红黑树+链表来管理。所以有必要再详细了解一下:
根节点和叶子结点必须是黑色;(保证不退化成链表)
红色必须有两个黑色子节点;任意节点到叶子节点黑色数量相同(保证任意节点到其每个叶子节点路径最长不会超过最短路径的2倍,不是相差1这么严格了)最短的肯定都是黑色的,最长的黑红相间的。

插入新节点最好是红色,因为任意节点到叶子节点黑色数量相同这一点没破坏,只需要黑红相间调整就好了。有五种情况:最简单的就是:如果是根节点,变黑色,如果父亲是黑色,不用调整;如果父亲是红色,就要看叔叔颜色以及左孩子还是右孩子,实现左旋右旋操作,最多三次就可完成;

删除的话也是看删除的是什么颜色,如果是红色直接孩子节点补上;如果是黑色,如果孩子红色,补上变色,如果孩子黑色,分成6种情况,很复杂。最终不超过3次操作完成;

数据库相关的树
B树和B+树,索引的底层结构
索引本身很大不可能存在内存,所以在磁盘。(保证树低,预读有效,减少IO次数)
B树是一颗平衡多叉查找树。传统二叉树对于数据量很大存储在磁盘的数据来说,性能太低了,因为树高很大,io次数很多。一般而言内存访问的时间约为 50 ns,而磁盘在 10 ms 左右,大部分时间阻塞在磁盘IO上。 B树每次把区域分成若干个区间,每次选取的更加精确。二叉树只分成两个。
第二就是磁盘是block读取的,每一页4kb就是一个B树节点,符合局部性原理,磁盘预读快,不然二叉树相邻元素不在一起,IO次数多。
二者结合使IO阻塞大。

B+树:是B树变形,主要两点
1.真正的数据只存在叶子结点,这点可以让每个节点可以存储更多的索引,导致树更加胖矮,IO次数更少。
2、叶子结点有指针相连,这保证非常适合范围查询,排序等场景。并且预读时一起加载到内存中,很快。

LSM树
中文意思大概是log结构合并的树。不是一种严格的树的结构,像HBASE,RocksDB都是用这种的;
核心思想是通过牺牲部分读性能和空间代价换来磁盘顺序写的高效写性能
但是空间可以通过压缩来优化,读性能可以通过布隆过滤器优化。

有层级架构,最上层的就是Memtable,保存在内存中并且有序。可以用跳表实现,也可以用别的。
当 MemTable达到一定大小后,会转化成Immutable MemTable,向下合并的过程。
再继续合并到sstable,是磁盘中的。
总之,就是更新操作先保存在内存中,积累一定数量再批量顺序写入磁盘。
代价就是:1.、冗余存储,不同sstable可能存在相同的key,可以压缩策略实现去除;压缩可以基于size和level。限制每一层大小和数量,或者限制层总大小。
2.读操作慢一点,要从最新的sstable倒着查询,找完所有的sstable才能确定,可以通过布隆过滤器实现加速查询。

猜你喜欢

转载自blog.csdn.net/weixin_53344209/article/details/131723047