1、树的概念
二叉树是指每个节点不能多余两个字节点,上面的图像就是二叉树
1.1 遍历二叉树
前序遍历:根->左->右
中序遍历:左->根->右
后序遍历:左->右->根
2、二叉查找树
2.1 概念
当前根节点的左边全部比根节点小
当前根节点的右边全部比根节点大
它的左右子树也可以都为二叉查找树
2.2 特性
- 查找基于类似二分查找的方法,正常情况下时间复杂度为O(logn)
- 极端情况下会退化为链表,查找时间复杂度变为O(n)
3、平衡二叉树(AVL树)
- 具有二叉查找树的全部优点
- 解决了二叉树极端情况会退化为链表的缺点(通过左旋右旋的方式),其最坏情况下查找时间复杂度也为O(logn)
- 每个节点的左子树和右子树的高度差至多等于1
4、红黑树
4.1 为什么有了平衡二叉树还需要红黑树
- 首先AVL树解决了二叉查找树极端情况下退化为链表的缺点,能够吧查找时间控制在O(logn)
- AVL需要保证每个节点的左子树和右子树的高度差至多等于1,导致每次插入/删除操纵会破坏这个规则,需要通过左旋/右旋操作来调整
- 在插入/删除很频繁的场景,平衡树需要及时调整导致性能大打折扣,于是有了红黑树,平衡树和红黑树插入操作最多都只需要两次旋转;但在删除操作中平衡树需要维护从被删node到根节点这条路径上所有node到平衡性,时间复杂度为O(logn),而红黑树最多只需要3次,即O(1)的复杂度;再有因为平衡树相比红黑树更为平衡,因此插入/删除操作平衡树破坏规则的概率要大于红黑树
4.2 特性
- 具有二叉查找树的特点
- 根节点是黑色的
- 每个叶子节点都是黑色的空节点,即不存储数据
- 任何相邻的节点不能同时为红色,即红色节点会被黑色节点隔开
- 每个节点,从该节点到其可达到叶子节点的所有路径,包含数目相同的黑色节点
正是由于红黑树的上述特点,使得它在最坏情况下查找时间复杂度为O(logn),可以说红黑树是一种不太平衡的平衡树,单看查找效率,平衡树要高于红黑树,但红黑树避免了插入删除时频繁调整结构的情况。
4.3 应用场景
STL中的map采用红黑树实现,其插入/删除/查找的时间复杂度均为O(logn)
4.4 红黑树与哈希表
红黑树 | 哈希表 | |
---|---|---|
特性 | 1、用来存储有序的数据,增删改查时间复杂度都为O(logn) 2、采用迭代器遍历红黑树的时间复杂度为O(n) | 1、正常情况下增删改查时间复杂度为O(1) |
缺点 | 1、相比于平衡树是一种折中的方案,在牺牲一定查找效率的情况下,增加了插入和删除效率 2、实际使用中如果查找频率大于插入/删除频率,选择平衡树,否则选择红黑树 | 1、插入数据较多时,冲突可能性变大,解决方法可在冲突的地方创建单链表,插入查找删除时间复杂度变为O(n) 2、哈希表中的元素是没有被排序的 3、hash表的resize非常耗时,且resize后所有数据需要rehash |
应用场景 | C++中的map和set | C++中的unrecorded_map和unrecorded_set |