本文主要是介绍数据结构乱七八糟的复习,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
复习循环队列:
public class QueueTest {private int[] array;private int front;private int rear;public QueueTest(int capacity) {this.array = new int[capacity];}public void enQueue(int element) throws Exception {if ((rear + 1) % array.length == front) {throw new Exception("队列已满");}array[rear] = element;rear = (rear + 1) % array.length;}public int deQueue() throws Exception {if (rear == front) {throw new Exception("队列已空!");}int deQueueElement = array[front];front = (front + 1) % array.length;return deQueueElement;}public void output() {for (int i = front; i != rear; i = (i + 1) % array.length) {System.out.println(array[i]);}}
}
散列表:
数组可以根据下标,进行元素的随机访问,散列表本质上也是一个数组。
可是数组只能是下标访问的方式,而散列表的Key则是以字符串类型为主的。
所以我们需要一个“中转站”,通过某种方式,把Key和数组下标进行转换,这个中转站就叫哈希函数。
实现:
Java中每个对象都有自己的hashCode,hashCode是区分不同对象的重要标识,无论对象自身类型是什么,他们的hashcode是一个整型变量。
既然都是整形变量,转化成数组下标,就按照数组长度进行取模运算。
实际JDK的哈希函数利用了位运算方式优化性能。在这里可以简单理解成取模操作。
------------------------------------
散列表的读写操作:
写操作就是在散列表中插入新的键值对(在JDK中叫做Entry)
哈希冲突就是通过哈希函数计算出来的哈希值相同,在往相同下标的数组中放key时,两个萝卜放到一个坑里,冲突不可避免,用开放寻址法和链表法解决。
开放寻址就是第二个萝卜往坑里放的时候,坑里已经有一个了,就往后移看看有没有多余的坑,没有继续往后移动,直到有多余的坑位,放进去,当然寻址方式很多种,不一定是简单的寻找当前元素的后一个元素看看有没有坑位这种方式。
Java的Thread Local就是开放寻址。
链表法:
数组的每个元素不仅是个Entry对象,还是一个链表的头节点,冲突时,next指向新的Entry即可。
-----------------------------------------------------------
读操作:
链表法:
通过哈希函数把key转化
找到数组下标为哈希值的链表,在链表中逐一查找,知道找到对应的key的值,取出其中的value。
-------------------------------------------------
扩容:
散列表达到一定饱和度,key映射冲突概率增加,链表长,影响性能,
1.扩容:就扩大当前数组长度的2倍
2.重新Hash:遍历原Hash数组,把所有Entry重新Hash到新数组中(经过扩容,原本拥挤的散列表变得稀疏,原有的Entry也重新得到了尽可能均匀的分配。)
1.8以后,hashmap优化 ,多个Entry被Hash到同一个数组下标位置时,为了提升查询效率会把Entry链表转化为红黑树。
这篇关于数据结构乱七八糟的复习的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!