2023 总结
```
数据结构
树
树的种类
无序树
树的任意节点的子节点没有顺序关系。
有序树
树的任意节点的子节点有顺序关系。
字典树
又称单词查找树,Trie树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是:利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较,查询效率比哈希树高。 它有 3 个基本性质: 根节点不包含字符,除根节点外每一个节点都只包含一个字符; 从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串; 每个节点的所有子节点包含的字符都不相同。
线索二叉树
在二叉树的结点上加上线索的二叉树称为线索二叉树,对二叉树以某种遍历方式(如先序、中序、后序或层次等)进行遍历,使其变为线索二叉树的过程称为对二叉树进行线索化。
二叉树
树的任意节点至多包含两棵子树。 二叉树遍历: 二叉树的遍历是指从二叉树的根结点出发,按照某种次序依次访问二叉树中的所有结点,使得每个结点被访问一次,且仅被访问一次。 二叉树的访问次序可以分为四种: 前序遍历 中序遍历 后序遍历 层次遍历
霍夫曼树
带权路径最短的二叉树称为哈夫曼树或最优二叉树。
二叉查找树(二叉搜索树、二叉排序树、BST)[这几个都是别名]
若任意节点的左子树不空,则左子树上所有节点的值均小于它的根节点的值; 若任意节点的右子树不空,则右子树上所有节点的值均大于它的根节点的值; 任意节点的左、右子树也分别为二叉查找树; 没有键值相等的节点。
平衡二叉树
它是一棵空树或它的左右两个子树的高度差的绝对值不超过 1,并且左右两个子树都是一棵平衡二叉树,同时,平衡二叉树必定是 BST。
AVL 树
在计算机科学中,AVL 树是最先发明的自平衡二叉查找树。在 AVL 树中任何节点的两个子树的高度最大差别为 1,所以它也被称为高度平衡树。增加和删除可能需要通过一次或多次树旋转来重新平衡这个树。 AVL 树本质上还是一棵二叉搜索树,它的特点是: 1.本身首先是一棵二叉搜索树。 2.带有平衡条件:每个结点的左右子树的高度之差的绝对值(平衡因子)最多为 1。 也就是说,AVL 树,本质上是带了平衡功能的二叉查找树(二叉排序树,二叉搜索树)。 使用场景: AVL 树适合用于插入删除次数比较少,但查找多的情况。 也在
Windows
进程地址空间管理中得到了使用 旋转的目的是为了降低树的高度,使其平衡
红黑树
红黑树是每个节点都带有颜色属性的二叉查找树,颜色或红色或黑色。在二叉查找树强制一般要求以外,对于任何有效的红黑树我们增加了如下的额外要求: 性质 1. 节点是红色或黑色。 性质 2. 根节点是黑色。 性质 3. 每个红色节点的两个子节点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色节点) 性质 4. 从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点。 使用场景: 红黑树多用于搜索,插入,删除操作多的情况下 红黑树应用比较广泛: 1. 广泛用在
C++
的STL
中。map
和set
都是用红黑树实现的。 2. 著名的linux
进程调度Completely Fair Scheduler
,用红黑树管理进程控制块。 3.epoll
在内核中的实现,用红黑树管理事件块 4.nginx
中,用红黑树管理timer
等
伸展树
伸展树(Splay Tree),也叫分裂树,是一种二叉排序树,它能在 O(log n)内完成插入、查找和删除操作。它由丹尼尔·斯立特 Daniel Sleator 和 罗伯特·恩卓·塔扬 Robert Endre Tarjan 在 1985 年发明的。 在伸展树上的一般操作都基于伸展操作:假设想要对一个二叉查找树执行一系列的查找操作,为了使整个查找时间更小,被查频率高的那些条目就应当经常处于靠近树根的位置。于是想到设计一个简单方法, 在每次查找之后对树进行重构,把被查找的条目搬移到离树根近一些的地方。伸展树应运而生。伸展树是一种自调整形式的二叉查找树,它会沿着从某个节点到树根之间的路径,通过一系列的旋转把这个节点搬移到树根去。 它的优势在于不需要记录用于平衡树的冗余信息。
替罪羊树
替罪羊树是计算机科学中,一种基于部分重建的自平衡二叉搜索树。在替罪羊树上,插入或删除节点的平摊最坏时间复杂度是O(log n),搜索节点的最坏时间复杂度是 O(log n)。 在非平衡的二叉搜索树中,每次操作以后检查操作路径,找到最高的满足 max(size(son_L),size(son_R))>alpha*size(this)的结点,重建整个子树。这样就得到了替罪羊树,而被重建的子树的原来的根就被称为替罪羊节点。替罪羊树替罪羊树是一棵自平衡二叉搜索树,由 ArneAndersson 提出。替罪羊树的主要思想就是将不平衡的树压成一个序列,然后暴力重构成一颗平衡的树。
B-tree(B 树)
一棵 m 阶 B 树(balanced tree of order m)是一棵平衡的 m 路搜索树。它或者是空树,或者是满足下列性质的树: 1、根结点至少有两个子女; 2、每个非根节点所包含的关键字个数 j 满足:┌m/2┐ - 1 <= j <= m - 1; 3、除根结点以外的所有结点(不包括叶子结点)的度数正好是关键字总数加 1,故内部子树个数 k 满足:┌m/2┐ <= k <= m ; 4、所有的叶子结点都位于同一层。
B 树(B-Tree)是一种自平衡的树,它是一种多路搜索树(并不是二叉的),能够保证数据有序。同时它还保证了在查找、插入、删除等操作时性能都能保持在
O(logn)
,为大块数据的读写操作做了优化,同时它也可以用来描述外部存储(支持对保存在磁盘或者网络上的符号表进行外部查找)
B+树
B+树是 B 树的一种变形形式,B+树上的叶子结点存储关键字以及相应记录的地址,叶子结点以上各层作为索引使用。一棵 m 阶的 B+树定义如下: (1)每个结点至多有 m 个子女; (2)除根结点外,每个结点至少有[m/2]个子女,根结点至少有两个子女; (3)有 k 个子女的结点必有 k 个关键字。 B+树的查找与 B 树不同,当索引部分某个结点的关键字与所查的关键字相等时,并不停止查找,应继续沿着这个关键字左边的指针向下,一直查到该关键字所在的叶子结点为止。 更适合文件索引系统 原因: 增删文件(节点)时,效率更高,因为 B+树的叶子节点包含所有关键字,并以有序的链表结构存储,这样可很好提高增删效率 使用场景: 文件系统和数据库系统中常用的 B/B+ 树,他通过对每个节点存储个数的扩展,使得对连续的数据能够进行较快的定位和访问,能够有效减少查找时间,提高存储的空间局部性从而减少 IO 操作。他广泛用于文件系统及数据库中,如: Windows:HPFS 文件系统 Mac:HFS,HFS+ 文件系统 Linux:ResiserFS,XFS,Ext3FS,JFS 文件系统 数据库:ORACLE,MYSQL,SQLSERVER 等中 B 树:有序数组+平衡多叉树 B+树:有序数组链表+平衡多叉树
B*树
B 树是 B+树的变体,在 B+树的非根和非叶子结点再增加指向兄弟的指针;B 树定义了非叶子结点关键字个数至少为(2/3)M,即块的最低使用率为 2/3(代替 B+树的 1/2)。 B+树的分裂:当一个结点满时,分配一个新的结点,并将原结点中 1/2 的数据复制到新结点,最后在父结点中增加新结点的指针;B+树的分裂只影响原结点和父结点,而不会影响兄弟结点,所以它不需要指向兄弟的指针; B 树的分裂:当一个结点满时,如果它的下一个兄弟结点未满,那么将一部分数据移到兄弟结点中,再在原结点插入关键字,最后修改父结点中兄弟结点的关键字(因为兄弟结点的关键字范围改变了);如果兄弟也满了,则在原结点与兄弟结点之间增加新结点,并各复制 1/3 的数据到新结点,最后在父结点增加新结点的指针; 所以,B*树分配新结点的概率比 B+树要低,空间使用率更高;
算法
复杂度分析
时间复杂度:
空间复杂度:
递归
计算机网络
网络模型(七层|五层|四层)
七层模型从上到下依次是:
应用层:协议有:HTTP FTP TFTP SMTP SNMP DNS TELNET HTTPS POP3 DHCP
表示层:数据的表示、安全、压缩。格式有,JPEG、ASCll、DECOIC、加密格式等
会话层:建立、管理、终止会话。对应主机进程,指本地主机与远程主机正在进行的会话
传输层:定义传输数据的协议端口号,以及流控和差错校验。协议有:TCP UDP,数据包一旦离开网卡即进入网络传输层
网络层:进行逻辑地址寻址,实现不同网络之间的路径选择。协议有:ICMP IGMP IP(IPV4 IPV6) ARP RARP
数据链路层:建立逻辑连接、进行硬件地址寻址、差错校验等功能。将比特组合成字节进而组合成帧,用 MAC 地址访问介质,错误发现但不能纠正。
物理层:建立、维护、断开物理连接。
TUP & UDP
用户数据报协议 UDP(User Datagram Protocol)
传输控制协议 TCP(Transmission Control Protocol)
TCP 和 UDP 的区别
TCP 的三次握手和四次挥手
HTTP & HTTPS
HTTP 是什么
HTTP 常见的状态码,有哪些?
HTTPS 是什么
操作系统
CPU
MySQL
索引
B 树和 B+树有什么不同呢?
B+ Tree 索引和 Hash 索引区别?
聚簇索引和非聚簇索引
覆盖索引
索引优化
存储引擎
数据和索引怎么组织设计,设计理念的不同也导致了 Innodb 和 Myisam 的出现,各自呈现独特的性能。
Innodb 引擎和 Myisam 引擎的区别
MyISAM 引擎的底层实现(非聚集索引方式)
Innodb 引擎的底层实现(聚集索引方式)
事务
事务
Java
JVM
Jvm 的内存结构
Java 的堆内存划分
Java 中的对象引用
垃圾回收算法
GC Roots 有哪些
回收垃圾对象内存的算法
垃圾回收机制(GC)
GC 性能调优
集合
Collection 集合
一、Collection 集合接口 Collection 是最基本的集合接口,一个 Collection 代表一组 Object,即 Collection 的元素, Java 不提供直接继承自 Collection 的类,只提供继承于的子接口(如 List 和 set)。 Collection 接口存储一组不唯一,无序的对象。
1、AbstractCollection
AbstractCollection 是 Java 集合框架中 Collection 接口 的一个直接实现类, Collection 下的大多数子类都继承 AbstractCollection ,比如 List 的实现类, Set 的实现类。它实现了一些方法,也定义了几个抽象方法留给子类实现,因此它是一个抽象类。
1.1、AbstractList
AbstractList 继承自 AbstractCollection 抽象类,实现了 List 接口 ,是 ArrayList 和 AbstractSequentiaList 的父类
1.1.1、AbstractSequentialList
什么是 AbstractSequentialList( Sequential 相继的,按次序的)AbstractSequentialList 没有什么特别的,这里是为了理解 LinkedList 更容易。AbstractSequentialList 继承自 AbstractList,是
LinkedList
的父类,是 List 接口 的简化版实现。简化在哪儿呢?简化在 AbstractSequentialList 只支持按次序访问,而不像 AbstractList 那样支持随机访问。想要实现一个支持按次序访问的 List的话,只需要继承这个抽象类,然后把指定的抽象方法实现就好了。需要实现的方法:1.2、AbstractSet
AbstractSet 没有提供具有 AbstractCollection 中的所有方法,并且只重写了equals,hashCode,removeAll 三个方法。
1、List 接口
List 接口是一个有序的 Collection,使用此接口能够精确的控制每个元素插入的位置,能够通过索引(元素在 List 中位置,类似于数组的下标)来访问 List 中的元素,第一个元素的索引为 0,而且允许有相同的元素。 List 接口存储一组不唯一,有序(插入顺序)的对象。
1.1、LinkedList
LinkedList 继承自 AbstractSequentialList 接口,同时了还实现了 Deque 接口。
我们知道 ArrayList 是以数组实现的,遍历时很快,但是插入、删除时都需要移动后面的元素,效率略差些。
而 LinkedList 是以链表实现的,插入、删除时只需要改变前后两个节点指针指向即可,省事不少。
1.2、ArrayList
ArrayList 是 Java 集合框架中 List接口 的一个实现类。可以说 ArrayList 是我们使用最多的 List 集合,它有以下特点:
容量不固定,想放多少放多少(当然有最大阈值,但一般达不到)
有序的(元素输出顺序与输入顺序一致)
元素可以为 null
效率高 size(), isEmpty(), get(), set() iterator(), ListIterator() 方法的时间复杂度都是 O(1)
add() 添加操作的时间复杂度平均为 O(n) 其他所有操作的时间复杂度几乎都是 O(n)
占用空间更小 对比 LinkedList,不用占用额外空间维护链表结构
2、Set 接口
Set 具有与 Collection 完全一样的接口,只是行为上不同,Set 不保存重复的元素。 Set 接口存储一组无序的、不可重复的对象
2.1、SortedSet
继承于 Set 保存有序的集合。
2.2、HashSet
HashSet 允许有 null 值。
HashSet 是无序的,即不会记录插入的顺序。
HashSet 不是线程安全的, 如果多个线程尝试同时修改 HashSet,则最终结果是不确定的。 须在多线程访问时显式同步对 HashSet 的并发访问。
HashSet 实现了 Set 接口。
2.3、LinkedHashSet
是 HashSet 的子类,底层使用了 LinkedHashMap,在 HashSet 的哈希表数据结构基础之上,增加了一个双向链表用来记录元素添加的顺序,能按照添加顺序遍历输出。需要频繁遍历的话效率可能高于 HashSet
2.4、 TreeSet
TreeSet 是一个有序的集合,它的作用是提供有序的 Set 集合。它继承了 AbstractSet 抽象类,实现了 NavigableSet<E>,Cloneable,Serializable 接口。TreeSet 是基于 TreeMap 实现的,TreeSet 的元素支持 2 种排序方式:自然排序或者根据提供的 Comparator 进行排序。
3、Queue 队列接口
Queue 继承自 Collection 接口,Deque, LinkedList, PriorityQueue, BlockingQueue 等类都实现了它。
除了继承 Collection 接口的一些方法,Queue 还添加了额外的 添加、删除、查询操作。
Queue 用来存放 等待处理元素 的集合,这种场景一般用于缓冲、并发访问。
3.1、Deque
Deque 是 Double ended queue (双端队列) 的缩写,读音和 deck 一样,蛋壳。
Deque 继承自 Queue,直接实现了它的有 LinkedList, ArayDeque, ConcurrentLinkedDeque 等。
Deque 支持容量受限的双端队列,也支持大小不固定的。一般双端队列大小不确定。
Deque 接口定义了一些从头部和尾部访问元素的方法。比如分别在头部、尾部进行插入、删除、获取元素。
Map 集合
二、 Map
Map 接口存储一组键值对象,提供 key(键)到 value(值)的映射。
1、AbstractMap
AbstractMap 是 Map 接口的的实现类之一,也是 HashMap, TreeMap, ConcurrentHashMap 等类的父类。 AbstractMap 提供了 Map 的基本实现,使得我们以后要实现一个 Map 不用从头开始,只需要继承 AbstractMap, 然后按需求实现/重写对应方法即可。
1.1、HashMap
HashMap 是一个采用哈希表实现的键值对集合,继承自 AbstractMap,实现了 Map 接口 。
HashMap 的特殊存储结构使得在获取指定元素前需要经过哈希运算,得到目标元素在哈希表中的位置,然后再进行少量比较即可得到元素,这使得 HashMap 的查找效率贼高。
当发生 哈希冲突(碰撞)的时候,HashMap 采用 拉链法 进行解决,因此 HashMap 的底层实现是 数组+链表
JDK 1.8 以前 HashMap 的实现是 数组+链表,即使哈希函数取得再好,也很难达到元素百分百均匀分布。
当 HashMap 中有大量的元素都存放到同一个桶中时,这个桶下有一条长长的链表,这个时候 HashMap 就相当于一个单链表,假如单链表有 n 个元素,遍历的时间复杂度就是 O(n),完全失去了它的优势。
针对这种情况,JDK 1.8 中引入了 红黑树(查找时间复杂度为 O(logn))来优化这个问题。
HashMap 的特点
底层实现是 链表数组,JDK 8 后又加了 红黑树
实现了 Map 全部的方法
key 用 Set 存放,所以想做到 key 不允许重复,key 对应的类需要重写 hashCode 和 equals 方法
允许空键和空值(但空键只有一个,且放在第一位,下面会介绍)
元素是无序的,而且顺序会不定时改变
插入、获取的时间复杂度基本是 O(1)(前提是有适当的哈希函数,让元素分布在均匀的位置)
遍历整个 Map 需要的时间与 桶(数组) 的长度成正比(因此初始化时 HashMap 的容量不宜太大)
两个关键因子:初始容量、加载因子
1.1.1、LinkedHashMap
LinkedHashMap 继承于 HashMap,迭代 HashMap 的顺序并不是 HashMap 放置的顺序,也就是无序。HashMap 的这一缺点往往会带来困扰,因为有些场景,我们期待一个有序的 Map。
这个时候,LinkedHashMap 就闪亮登场了,它虽然增加了时间和空间上的开销,但是通过维护一个运行于所有条目的双向链表,LinkedHashMap 保证了元素迭代的顺序。该迭代顺序可以是插入顺序或者是访问顺序。
1.2、ConcurrentHashMap
1.3、Hashtable
与 HashMap 一样,Hashtable 也是一个散列表,它存储的内容是键值对(key-value)映射。Hashtable 继承于 Dictionary,实现了 Map、Cloneable、java.io.Serializable 接口。Hashtable 的函数都是同步的,这意味着它是线程安全的。它的 key、value 都不可为 null。Hashtable 中的映射不是有序的。
1.4、TreeMap
TreeMap 提供了一种以排序顺序存储键/值对的有效方法。它是基于红黑树的 NavigableMap 实现。继承自 AbstractMap,实现了 NavigableMap 接口。
1.5、IdentityHashMap
IdentityHashMap 与 HashMap 都是,继承自 AbstractMap,实现了 Map 接口 。不同的是,其比较键(或值)时,使用引用相等性代替对象相等性。
1.6、WeakHashMap
WeakHashMap 与正常的 HashMap 类似,不同点在 WeakHashMap 的 key 是「弱引用」的 key。WeakHashMap 具有弱引用的特点:随时被回收对象。 继承自 AbstractMap,实现了 Map 接口。
2.1、Map.Entry 的作用
Map.Entry 是为了更方便的输出 map 键值对。一般情况下,要输出 Map 中的 key 和 value 是先得到 key 的集合 keySet(),然后再迭代(循环)由每个 key 得到每个 value。values()方法是获取集合中的所有值,不包含键,没有对应关系。而 Entry 可以一次性获得这两个值。
2.2、SortedMap 继承于 Map,使 Key 保持在升序排列。
2.2.1、NavigableMap
NavigableMap(
java.util.NavigableMap
)接口是SortedMap的子接口,但是 NavigableMap 接口中新加了几个 SortedSet 接口中没有的方法,使导航存储在映射中的键和值成为可能。
三、Vector
Vector 类实现了一个动态数组和 ArrayList 很相似,但是该类是同步的,可以用在多线程的情况,该类允许设置默认增长长度,默认扩容方式为原来的 2 倍。
1、Stack
Stack 继承自 Vector
Stack 栈是一个 "先进后出"的原理
Stack 本质是一个 List,其具备 List 所有方法
四、Dictionary
Dictionary 类是一个抽象类,用来存储键/值对,作用和 Map 类相似。
1、Hashtable
与 HashMap 一样,Hashtable 也是一个散列表,它存储的内容是键值对(key-value)映射。Hashtable 继承于 Dictionary,实现了 Map、Cloneable、java.io.Serializable 接口。Hashtable 的函数都是同步的,这意味着它是线程安全的。它的 key、value 都不可为 null。Hashtable 中的映射不是有序的。
1.1、Properties
Properties 继承于 Hashtable。表示一个持久的属性集.属性列表中每个键及其对应值都是一个字符串。
BitSet
Java 平台的 BitSet 用于存放一个位序列,如果要高效的存放一个位序列,就可以使用位集(BitSet)。由于位集将位包装在字节里,所以使用位集比使用 Boolean 对象的 List 更加高效和更加节省存储空间。
集合算法
迭代器(lterator)
评论