持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第21天,点击查看活动详情
哈希表
哈希表
去对比之前我们的线性表,树,图哪些,我们在查找的时候要去比较,而在哈希表中,若在理想情况下,哈希函数是有一一对应的映射关系的,这样我们在查找的时候直接通过函数可以直接找到,不用比较。但是这仅仅是在理想情况下,所以肯定是有冲突的,我们只能说要尽量去避免这种冲突。所以构建哈希表需要有哈希函数和处理冲突的方法。如下图是将关键字序列存到一个记录表中,采用的hash函数是:除留取余法,采用冲突解决的办法是:线性探测法
代码实现
在代码中,我们看到hashSearch方法在查找时,就没有需要去和元素进行比较,而是查找过程产生冲突则按照解决冲突的办法依次往下查找。(当然若没有冲突的时候是最好的一次就找到,理想情况下他的时间复杂度可以是O(1))
public DataArray(int[] paraKeyArray, String[] paraContentArray, int paraLength) {
// Step 1. Initialize.
length = paraLength;
data = new DataNode[length];
for (int i = 0; i < length; i++) {
data[i] = null;
} // Of for i
// Step 2. Fill the data.
int tempPosition;
for (int i = 0; i < paraKeyArray.length; i++) {
// Hash.
tempPosition = paraKeyArray[i] % paraLength;
// Find an empty position
while (data[tempPosition] != null) {
tempPosition = (tempPosition + 1) % paraLength;
System.out.println("Collision, move forward for key " + paraKeyArray[i]);
} // Of while
data[tempPosition] = new DataNode(paraKeyArray[i], paraContentArray[i]);
}
}
public String hashSearch(int paraKey) {
int tempPosition = paraKey % length;
while (data[tempPosition] != null) {
if (data[tempPosition].key == paraKey) {
return data[tempPosition].content;
} // Of if
System.out.println("Not this one for " + paraKey);
tempPosition = (tempPosition + 1) % length;
}
return "null";
}
键值对
在昨天和今天的学习中,有开始学到键值对了,实际上,在java中,键值对使用是非常方便的,可以存储任何类型,键即我们的key,值即我们的value。而在java中有一种比较常用的数据类型就是HashMap,如下图这个类名是HashMap的(我这里只复制了其类名,相关的成员变量和方法没有复制).它使用泛型类来创建对象的。
public class HashMap<K, V> extends AbstractMap<K, V> implements Map<K, V>, Cloneable, Serializable {}
而HashMap底层采用的其实就是哈希表这种数据结构来存储数据的,采用的是拉链法,可以存储任何数量的键值对象,但是键不能发生冲突,若键相同,则会覆盖原数据。
总结
今天学习的是哈希表的初始化,从之前代码的学习到现在,主要的数据结构存储有三种就是数组结构,链表结构和今天学习的哈希表结构,对于数组结构,它的存储是需要分配连续空间,在插入删除比较麻烦,查找方便。链表结构它的查找就很慢,但是插入删除很方便,不用移动指针,而哈希表结构结合了数组和链表结构,(这里哈希表以拉链法实现)。查找效率和删除插入效率都可以很方便。