0
点赞
收藏
分享

微信扫一扫

150-链式哈希表实现

兵部尚输 2022-05-05 阅读 64

C++、Java无序关联容器底层采用链式哈希表实现。
为什么不采用线性探测哈希表?
如果采用线性探测哈希表,缺陷是:

  • 2、发生哈希冲突时,需要从当前发生哈希冲突的位置向后不断的去找,找到第一个空闲的位置把元素放上,这个过程的时间复杂度就趋近于O(n)了,存储变慢了,查询和删除也变慢,哈希冲突的发生越严重,就越靠近O(n)的时间复杂度,这个时间复杂度能否优化?哈希冲突是无法避免的,但是发生哈希冲突以后,在进行增删查的时候,能不能把时间效率提高一点,不让它趋近于O(n)的时间复杂度呢?不能,因为它是一个线性表,是数组,得环形遍历,趋近于O(n),按一个位置一个位置找,找的越多,时间复杂度就靠近O(n),这个是无法优化的,因为只有这么一个数组的结构。这个问题在线性哈希表中,无法优化,但是在链式哈希表中是可以优化的

  • 2、在多核盛行的情况下,非常方便的使用并发程序(多线程,多进程),在多线程环境中,有线程安全的问题,**多个线程能不能同时在一个数组中进行数据的增删查呢?肯定是不可以的!!!**在C++的所有容器都不是线程安全的,所以我们必须添加线程的互斥操作,互斥锁,读写锁,自旋锁,然后在多线程下对容器的添加修改删除做互斥操作,保证这些容器在多线程环境下操作它都是一个原子操作。同样的,线性哈希表作为一个数组,没有办法去一边修改一边查询的,或者一边删除一边查询。

  • 很明显,在线性哈希表中,往数组增加一个元素,又要通过除留余数法计算哈希值,发生哈希冲突了,又要遍历数组找到一个空闲的位置放,这么多的操作能是一个原子操作吗?肯定不能是一个原子操作,这步骤太多了。

  • 在多线程环境中,线性探测所用到的基于数组实现的哈希表只能给全局的表用互斥锁来保证哈希表的原子操作,保证线程安全。

  • (因为线性探测只有一个数组,得把整个数组锁起来,也就是说,多个线程,对同1个数组操作,如果多个线程对这个数组添加的元素是不在同一个位置上的,理论来说,应该可以并发运行,实际上不能让他们并发,因为有可能多个线程,你要放在3位置,我要放在4位置,然后3和4位置原本已经有元素了,你和我就都发生哈希冲突了,都要向后找第一个空闲的位置,如果我和你同时找到了1号位置,如果我和你都认为1号位置是空闲,都放元素进去,后放的那个元素把先放的元素给覆盖掉了,这就有问题了!!!)

  • 所以,我们给整个哈希表加锁了,要么你先操作,要么我先操作。(不具备并发能力)

但是,链式哈希表在多线程环境下可以采用分段的锁,既保证了线程安全,又有一定的并发量,提高了效率。
当然,我们库里的无序关联容器并没有实现多线程环境中的线程安全问题,也就是并没有去加锁,但是毫不妨碍当我们真真正正想实现一个线程安全,运行在多线程环境下的一个基于哈希表实现的无序关联容器,我们在代码上就可以通过分段锁来实现!

链式哈希表

举报

相关推荐

0 条评论