【数据结构与算法】第四章 散列(解决查找问题)

第四章 散列(解决查找问题)

1、散列是一种用于以常数平均时间执行插入、删除和查找的技术。它解决的是数组的值的快速查找问题。

2、它解决的是查询的时候可以达到O(1)的时间复杂度。因为它底层是一个数组。所以可以随机的定位。

3、散列的底层是数组,但又不同于普通的数组。它牺牲了排序性,同样findMin\findMax这样的方法也不适用。它提高的是对值的查找效率。使得数值和索引下标可以进行改换。这个不同于普通数组。

 

一、hash结构

从上图我们可以看出,这种hash结构有两部分组成,数组和链表。(jdk1.7是基于数组+链表。jdk1.8是数组+红黑树)

每个数组元素里面存的是链表。

 

二、实现方式

 

从上图我们可以总结出以下流程:

还有几个关键字:

hashCode、hash、哈希冲突、存储

我们把流程进行分解:

1、得到key的hashCode()值

对于java每个类都默认实现了hashCode()方法如下:

  • Object类的hashCode返回对象的内存地址经过处理后的结构,由于每个对象的内存地址都不一样,所以哈希码也不一样。 
  • String类的hashCode根据String类包含的字符串的内容,根据一种特殊算法返回哈希码,只要字符串所在的堆空间相同,返回的哈希码也相同。 
  • Integer类,返回的哈希码就是Integer对象里所包含的那个整数的数值

 

2、进行hash()得到索引下标

private int myHash(T x){

    int hashVal = x.hashCode();

    hashVal % = theLists.length;  /theLists.length一定是一个素数,不了值更分散

    if(hashVal <0)

        hashVal += theLists.length;

    return hashVal;

}

//得到根据hash取模得到索引位置

//private int hash(T key) {

   // return (key.hashCode() & 0x7fffffff) % M;

// }

 

0x7fffffff 表示0后面31个1.

&按位与  目地是把hashCode的值去除符号。都表示正的。

最后取M的模,存入相应的地址中去。

 

 

取模是有技巧的,对于素数取模才能让索引更加分散。

 

 

3、存储数值

 

这个比较简单,根据索引下标,找到该索引内存储的LinkedList对象。进行add()

当然这里面也涉及到rehash的过程。也就是说,当hash结构存储的size==theLists.length时,进行rehash.重新开辟一块数组内存空间。对hash结构的所有元素重新进行hash存储。

一般是2倍的当前length,取合适的素数。

 

 

代码如下:

//添加元素

public void add(T key) {

    int index = this.hash(key);

    MyLinkedList myLinkedLists = theLists[index];

    if (!myLinkedLists.contains(key)) {

        myLinkedLists.add(key);

        size++;

        if (size > M) {     //以空间换时间

            this.resize(2 * theLists.length);

        }

    }

}

 

//扩容

private void resize(int newM) {

    MyLinkedList<T>[] newLists = new MyLinkedList[newM];

    //先初始化newLists的元素

    for (int i = 0; i < newM; i++) {

        newLists[i] = new MyLinkedList<T>();

    }

    //遍历所有元素,重新存储

    for (int i = 0; i < theLists.length; i++) {

        MyLinkedList<T> myLinkedList = theLists[i];

        for (int j = 0; j < myLinkedList.size(); j++) {

            T key = myLinkedList.get(0);

            newLists[hash(key)].add(key);

        }

    }

    this.M = newM;

    this.theLists = newLists;

}

 

三、总结

 

 

ConcurrentHashMap:

https://blog.csdn.net/yy1098029419/article/details/79672753

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值