1
- # 1 有序表原理及扩展
2
-
3
- ## 1.1 搜索二叉树
1
+ - [ 1 有序表原理及扩展] ( #1 )
2
+ * [ 1.1 搜索二叉树] ( #11 )
3
+ * [ 1.2 搜索二叉树的增删改查] ( #12 )
4
+ + [ 1.2.1 搜索二叉树的查找和添加] ( #121 )
5
+ * [ 1.3 传统搜索二叉树存在的问题] ( #13 )
6
+ + [ 1.3.1 平衡搜索二叉树] ( #131 )
7
+ + [ 1.3.2 左旋和右旋] ( #132 )
8
+ * [ 1.4 有序表] ( #14 )
9
+ * [ 1.5 有序表的实现(AVL树,SB树,红黑树)] ( #15 )
10
+ + [ 1.5.1 AVL树] ( #151 )
11
+ - [ 1.5.1.1 AVL树针对某个节点的平衡性处理] ( #1511 )
12
+ + [ 1.5.2 SB树] ( #152 )
13
+ - [ 1.5.2.1 SB树针对某个节点的平衡性处理] ( #1521 )
14
+ + [ 1.5.3 红黑树] ( #153 )
15
+ - [ 1.5.3.1 红黑树针对某个节点的平衡性处理] ( #1531 )
16
+ * [ 1.5.3.1.1 Redis为什么选择跳表的结构?] ( #15311 )
17
+ * [ 1.6 跳表SkipList(也可实现有序表功能)] ( #16 )
18
+ * [ 1.7 有序表例题实战] ( #17 )
19
+ + [ 1.7.1 哪些情况下需要改写系统的有序表?] ( #171 )
20
+
21
+ <h1 id =' 1 ' >1 有序表原理及扩展</h1 >
22
+
23
+ <h2 id =' 11 ' >1.1 搜索二叉树</h2 >
4
24
5
25
经典的搜索二叉树,是没有重复值的,任何节点为头的数,左孩子都比自己小,右孩子都比自己大
6
26
15
35
3、如果有重复节点的需求,可以在一个节点内部增加数据项
16
36
17
37
38
+ <h2 id =' 12 ' >1.2 搜索二叉树的增删改查</h2 >
18
39
19
- ## 1.2 搜索二叉树的增删改查
20
-
21
-
22
- ### 1.2.1 搜索二叉树的查找和添加
40
+ <h2 id =' 121 ' >1.2.1 搜索二叉树的查找和添加</h2 >
23
41
24
42
- 查找
25
43
@@ -489,8 +507,7 @@ public class AbstractBinarySearchTree {
489
507
490
508
```
491
509
492
-
493
- ## 1.3 传统搜索二叉树存在的问题
510
+ <h2 id =' 13 ' >1.3 传统搜索二叉树存在的问题</h2 >
494
511
495
512
496
513
1)基础的搜索二叉树,添加、删除时候不照顾平衡性
@@ -506,13 +523,13 @@ public class AbstractBinarySearchTree {
506
523
平衡二叉树的定义,任何子树,左子树的高度和右子树的高度差,不大于1。所以对于n个节点,平衡二叉树的高度,就是logN
507
524
508
525
509
- ### 1.3.1 平衡搜索二叉树
526
+ < h3 id = ' 131 ' > 1.3.1 平衡搜索二叉树</ h3 >
510
527
511
528
512
529
平衡搜索二叉树,就是在插入和删除的过程中,动态的保持平衡性。保持平衡的代价保持在logN。平衡搜索二叉树的实现由很多,红黑树只是其中一种
513
530
514
531
515
- ### 1.3.2 左旋和右旋
532
+ < h3 id = ' 132 ' > 1.3.2 左旋和右旋</ h3 >
516
533
517
534
左旋和右旋针对头结点而言的,即对哪个头结点进行左旋还是右旋;顾名思义如果对头结点为a的子树右旋,那么a倒到右边,a的左孩子顶上来,到a原来的位置上去。a原来左孩子的右孩子,现在当做a的左孩子,如下图
518
535
@@ -641,8 +658,7 @@ extends AbstractBinarySearchTree {
641
658
```
642
659
643
660
644
-
645
- ## 1.4 有序表
661
+ <h2 id =' 14 ' >1.4 有序表</h2 >
646
662
647
663
648
664
在Java中,就是TreeMap,有序表和Hash表(HashMap)的操作类似,但是有序表中自动把我们的key排好了顺序,我们也可以传入比较器,自定义对比和排序的规则;我们可以通过TreeMap直接得到最大节点和最小节点,也可以获取大于某个值的第一个Key是什么等等
@@ -658,7 +674,7 @@ extends AbstractBinarySearchTree {
658
674
2、使用有序表的Key必须是可以比较的,没法自然比较的需要传入自定义比较器
659
675
660
676
661
- ## 1.5 有序表的实现(AVL树,SB树,红黑树)
677
+ < h2 id = ' 15 ' > 1.5 有序表的实现(AVL树,SB树,红黑树)</ h2 >
662
678
663
679
在有序表中,有序表是一种规范,类似于接口名。规范为key要按序组织,所有操作要是O(logN)等。各种树结构可以实现有序表的功能。其中红黑树只是有序表的一个实现
664
680
@@ -688,8 +704,8 @@ AVL树最严格、SB树稍宽松、红黑树最宽松
688
704
689
705
690
706
707
+ <h3 id =' 151 ' >1.5.1 AVL树</h3 >
691
708
692
- ### 1.5.1 AVL树
693
709
694
710
是这三个平衡搜索二叉树中,平衡性最严格的,左树高度和右树高度的绝对值,严格小于2
695
711
@@ -698,7 +714,8 @@ AVL树在插入节点的时候,只会向上检查节点的平衡性有没有
698
714
==实质上三种树删除和插入节点,检查哪些节点需要调整平衡都是这样的查找规则,对于删除来说,只有左树和只有右树没影响,如果左右树都存在,是去检查后继节点原来所在的位置向上的平衡性。只是具体到某个节点平衡性的处理上,三种树不一样==
699
715
700
716
701
- #### 1.5.1.1 AVL树针对某个节点的平衡性处理
717
+ <h4 id =' 1511 ' >1.5.1.1 AVL树针对某个节点的平衡性处理</h4 >
718
+
702
719
703
720
1、该节点左树高度和右树高度差的绝对值|L-R|,小于2。不违规,无须调整
704
721
@@ -1003,7 +1020,7 @@ public class AVLTree extends AbstractSelfBalancingBinarySearchTree {
1003
1020
```
1004
1021
1005
1022
1006
- ### 1.5.2 SB树
1023
+ < h3 id = ' 152 ' > 1.5.2 SB树</ h3 >
1007
1024
1008
1025
1009
1026
对于平衡性而言,任何叔叔节点的子节点格式,不少于该节点的任何一个侄子节点子节点的个数
@@ -1025,7 +1042,8 @@ e-->g
1025
1042
1026
1043
对于这种约束,也可保证任何节点的左右节点的个数不会有很大悬殊,即使高度不满足严格相减的绝对值小于2,也无伤大雅。整体仍然是O(logN)
1027
1044
1028
- #### 1.5.2.1 SB树针对某个节点的平衡性处理
1045
+ <h4 id =' 1521 ' >1.5.2.1 SB树针对某个节点的平衡性处理</h4 >
1046
+
1029
1047
1030
1048
2007年,读高中的时候,承志峰研究出来的;常被用作比赛时,AVL树反而在ACM比赛中使用的相对少点
1031
1049
@@ -1705,7 +1723,7 @@ public class Code02_SizeBalancedTreeMap {
1705
1723
```
1706
1724
1707
1725
1708
- ### 1.5.3 红黑树
1726
+ < h3 id = ' 153 ' > 1.5.3 红黑树</ h3 >
1709
1727
1710
1728
1、 节点有红有黑
1711
1729
@@ -1719,8 +1737,7 @@ public class Code02_SizeBalancedTreeMap {
1719
1737
从第三点和第四点可以推出,任何长链(黑红交替)和任何段链(都为黑)保证黑一样多,那么长链的长度一定不会比短链长度的二倍还要大。实质上上面条件的目的也是保证最长的链不要比最短的链2倍还多,一定程度上保证了平衡性
1720
1738
1721
1739
1722
-
1723
- #### 1.5.3.1 红黑树针对某个节点的平衡性处理
1740
+ <h4 id =' 1531 ' >1.5.3.1 红黑树针对某个节点的平衡性处理</h4 >
1724
1741
1725
1742
红黑树本质上也是搜索二叉树,搜索二叉树怎么增加和删除节点,红黑树相同;同样的加完节点,删除完节点,之后从受影响的节点往上都进行平衡性检查,几种有序表的实现只有检查平衡性的评估指标不同
1726
1743
@@ -1744,8 +1761,7 @@ public class Code02_SizeBalancedTreeMap {
1744
1761
1745
1762
红黑树,在(AVL,SB) 和 硬盘的树(B,B+)树之间达到平衡。各有取舍
1746
1763
1747
-
1748
- ##### Redis为什么选择跳表的结构?
1764
+ <h5 id =' 15311 ' >1.5.3.1.1 Redis为什么选择跳表的结构?</h5 >
1749
1765
1750
1766
Redis为什么选择跳表的结构,而不是AVL和SB树呢,实质上可以选择,但是考虑到redis可能需要对有序表进行序列化的要求,SkipList就是多层的线性结构,比较好序列化。AVL和SB是个结构化的东西,不好序列化;一种技术的选型,需要根据自己的生存状态去选择的
1751
1767
@@ -1755,7 +1771,7 @@ Redis为什么选择跳表的结构,而不是AVL和SB树呢,实质上可以选
1755
1771
1756
1772
1757
1773
1758
- ## 1.6 跳表SkipList(也可实现有序表功能)
1774
+ < h2 id = ' 16 ' > 1.6 跳表SkipList(也可实现有序表功能)</ h2 >
1759
1775
1760
1776
1761
1777
==最烧脑的结构==
@@ -2050,8 +2066,7 @@ public class Code03_SkipListMap {
2050
2066
```
2051
2067
2052
2068
2053
-
2054
- ## 1.7 有序表例题实战
2069
+ <h2 id =' 17 ' >1.7 有序表例题实战</h2 >
2055
2070
2056
2071
- 例题1
2057
2072
@@ -2072,7 +2087,7 @@ public class Code03_SkipListMap {
2072
2087
整个流程,只需要运用有序表的基本功能,原始的有序表已经能够满足需求,无需改写有序表,用系统实现的即可;
2073
2088
2074
2089
2075
- ### 1.7.1 哪些情况下需要改写系统的有序表?
2090
+ < h3 id = ' 171 ' > 1.7.1 哪些情况下需要改写系统的有序表?</ h3 >
2076
2091
2077
2092
- 例题-leetcode原题
2078
2093
0 commit comments