Hash
Hash的概念和基本特征
哈希(Hash)也称为散列,就是把任意长度的输入,通过散列算法
,变换成固定长度的输出,这个输出值就是散列值。
这里的映射到底是什么意识 ? 为什么访问的时间复杂度
是O(1) ?
我们现在假设数组array存放的是1到15这些数,现在要存在一个大小是7的Hash表中.假设我
们存储的位置计算公式是
idnex = number % 7
我们把 1 到 6 都放入这里的元素
然后继续存储 7 到 13
让后继续存储 14 到 15
实际情况是:
这样处理之后,如果我们需要拿到 13 ,我们使用我们的公式 13 % 7 = 6 直接访问 array[6]明显可以访问到返回 true
。如果我们要测试 20 是否再里面,我们使用公式 20 % 7 = 6 发现没有直接返回 false
碰撞处理方法
上面的例子中我们发现有每一个索引位置都有重复的元素。两个不同的输入值,根据同一散列函数计算出的散列值相同的现象叫做碰撞
解决方法:
- 链地址法(Separate Chaining)
- 开放地址法
- 再哈希法
- …
我们重点了解 开放地址法 和 链地址法
开放地址法
开放地址法,当产生碰撞时,会在哈希表中寻找其他空闲位置
来存储冲突的元素。
8 本来要要到 1 位置但是 1 位置满了,所以向前找空位置
链地址法
哈希将每一个链表单元作为链表的头节点 ,发生冲突时直接把元素插入到头节点后面即可。
但是这种方式还需要很多优化,底层会比较复杂
需要注意的两点
- 数组长度必须时 2^n
- entry 的个数小于数组长度的 75% 否则直接扩容了
队列基础知识
队列的概念和基本特征
队列和栈相反时先进先出。队列最大的作用时缓存
队列其实就像是,我们去餐厅吃饭领号一样,一个一个处理,慢慢解决!比如,在操作系统的进程和线程,比如进程太多了导致了阻塞,那么我们就先用队列把新任务存一下,之后慢慢处理
实现队列
public class LinkQueue {
private Node front;
private Node rear;
private int size;
public LinkQueue() {
this.front = new Node(0);
this.rear = new Node(0);
}
/**
* 入队
*/
public void push(int value) {
Node newNode = new Node(value);
Node temp = front;
while (temp.next != null) {
temp = temp.next;
}
temp.next = newNode;
rear = newNode;
size++;
}
/**
* 出队
*/
public int pull() {
if (front.next == null) {
System.out.println("队列已空");
}
Node firstNode = front.next;
front.next = firstNode.next;
size--;
return firstNode.data;
}
/**
* 遍历队列
*/
public void traverse() {
Node temp = front.next;
while (temp != null) {
System.out.print(temp.data + "\t");
temp = temp.next;
}
}
static class Node {
public int data;
public Node next;
public Node(int data) {
this.data = data;
}
}
//测试main方法
public static void main(String[] args) {
LinkQueue linkQueue = new LinkQueue();
linkQueue.push(1);
linkQueue.push(2);
linkQueue.push(3);
System.out.println("第一个出队的元素为:" + linkQueue.pull());
System.out.println("队列中的元素为:");
linkQueue.traverse();
}
}