数据结构小记
数组
- 固定长度
- 一旦申请完毕 长度固定
- 索引从0开始
- 连续
- 无论从逻辑上
- 还是物理上都是连续
- 随机存取
- 指的是数组的可以通过下标索引直接方位对应元素
链表
- 由节点组成
- 在物理上可以不连续
- 删除 插入 是很快的
- 双向链表 和 单项链表
- 不具备随机存取
- 单链表成环
- 单链表反转
栈
- 先进后出
队列
- 先进先出
双栈实现一个队列
package CeShi;
import java.util.Stack;
/**
* @author muzi
* @description 双栈实现队列
* @date 2021年08月16日 17:31
*/
public class TwoStack {
private Stack a;
private Stack b;
public TwoStack(Stack a, Stack b) {
this.a = a;
this.b = b;
}
public boolean isEmpty(){
if (a.isEmpty() && b.isEmpty()) return true;
else return false;
}
public void push(int val){
a.push(val);
}
public int pop(){
if (b.isEmpty()){
while (!a.isEmpty()){
b.push(a.pop());
}
}
return Integer.parseInt(b.pop().toString());
}
public static void main(String[] args) {
TwoStack twoStack = new TwoStack(new Stack(),new Stack());
twoStack.push(1);
twoStack.push(2);
twoStack.push(3);
while (!twoStack.isEmpty()){
System.out.print(twoStack.pop() + " ");
}
System.out.println();
Stack a = new Stack();
a.push(1);
a.push(2);
a.push(3);
while (!a.isEmpty()){
System.out.print(a.pop() + " ");
}
}
}
树
-
二叉树
- 深度
- 先序遍历 100 50 10 -20 15 70 200 150 300
- 中序遍历
- 后序遍历
- 广度
- 层次遍历
- 深度
-
搜索二叉树
- 左小右大
-
平衡二叉树
- 任意一个节点的左右子树高度差不大于1
-
完全二叉树
-
满二叉树
-
大顶推 小顶堆
- 堆排序
-
红黑树
- 心是黑的 ->根是黑的
- 要么红要么黑 -> 节点只有这两种颜色
- 两颗红心不能在一起 ->不能有两个连续红色节点
- 所有路径经过黑色节点数目一致
- 近似平衡的二叉树 实现 继续保持红黑树的操作要简单
- TreeMap
- HashMap 1.8
- O(logn)
编码方式
- 定长编码:(所有字符的编码长度统一固定)消耗的资源太大
- 变长编码:(很大程度上节省空间)但要保证无歧义
哈夫曼树:
参考这个地址 https://www.cnblogs.com/LiaHon/p/11203229.html
-
前缀编码(即要求一个字符的编码不能是另一个字符编码的前缀)
-
信息数据都在叶子节点
-
哈夫曼树构造不唯一(因为在构造的时候,当前两个最小值构成可能不唯一);但树的带权路径长度一定唯一(所有结点-从根结点到该结点之间的路径长度与该结点的权的乘积-的和)
为什么B树比二叉树应用更广泛,明明查找效率近似?
-
不同的结点是需要从磁盘读取到内存由CPU解解读的,IO操作很消耗时间(ms)级的,但是当结点读取到内存后,在结点内部进行的查找是CPU级的很快;
-
B树(多叉)减少IO操作(同时:B树(多叉)相对层数低,减少了IO的次数),节省查询时间,提高效率
B+树对于B树而言呢?
-
查找稳定:B树的查找可能在任意一个地方结束查找;但是B+树只在叶子结点结束查找。
-
范围查询更快:所有叶子节点形成有序链表,便于范围查询
-
IO操作次数少:由于B+树只在叶子节点存储数据,中间结点存放索引(数据是很消耗内存的)那么同样一次IO操作,B+树获取的查找范围更广,更有利于查找
B树
- 关键字集合分布在整颗树中;
- 任何一个关键字出现且只出现在一个结点中;
- 搜索有可能在非叶子结点结束;
- 其搜索性能等价于在关键字全集内做一次二分查找;
- 自动层次控制;
B+树
- 所有关键字都出现在叶子结点的链表中(稠密索引),且链表中的关键字恰好是有序的;
- 不可能在非叶子结点命中;
- 非叶子结点相当于是叶子结点的索引(稀疏索引),叶子结点相当于是存储(关键字)数据的数据层;
- 更适合文件索引系统;
B*树
HashMap
- Key - Value
- 用key 做hash定位,将value存入hashMap中
Hash/Hash表
-
为了追求更高的查找效率,研究数据结构;数组O(1) -> 下标索引 随机存取;于是:想到了一种办法,某一个数据,根据一种算法,它在数组中只有一个固定的位置,固定映射
-
固定映射
- 求余法
- 直接寻址
- 数字分析
- 平方取中
-
hash冲突
- 拉链法
- 开放定址法
- 再哈希
- 建立公共溢出区
JDK1.7
- 头插法
- hash()->4次扰动
- 先扩容再插入
- 数组 + 链表
JDK1.8
- 尾插法(解决了扩容时死循环的问题)
- hash()->1次扰动
- 先插入再插入(当插入时发现确实需要扩容,才扩容;避免无效扩容)
- 数组 + 链表/(红黑树)
- 当前链表长度>=8,数组长度>64
hash()->4次扰动
- 先扩容再插入
- 数组 + 链表
JDK1.8
- 尾插法(解决了扩容时死循环的问题)
- hash()->1次扰动
- 先插入再插入(当插入时发现确实需要扩容,才扩容;避免无效扩容)
- 数组 + 链表/(红黑树)
- 当前链表长度>=8,数组长度>64