数据结构—哈希表

一、哈希表概念

哈希表(Hash Table):也叫散列表。是根据关键码值(Key Value)直接进行访问的数据结构。

哈希表通过(键 key )(映射函数 Hash(key) )计算出对应的(值 value),把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做(哈希函数(散列函数)),存放记录的数组叫做(哈希表(散列表))。

二、哈希表的操作

关于哈希表,有两种操作:建立和查询

1.向哈希表中插入一个关键码值

        将键(key)通过哈希函数转化为 值(value)并存放在哈希表中

2. 在哈希表中搜索一个关键码值

        使用相同的哈希函数转化为 值(value)再在哈希表中查询

当处理数据为整型时,键(key)的大小通常为元素大小,再进行映射函数计算值,大致原理如下

 三、哈希函数

        概念:将哈希表中元素的键值映射为元素存储位置(值)的函数

哈希函数一般要满足以下条件:


 ①  易于计算,并且计算出来的值分布均匀(避免出现过多的哈希冲突)

 ②  哈希函数计算出的哈希值是一个固定长度的输出值

③  一个键值不能对应两个hash值对应:

        如果Hash(key1)!=Hash(key2) 那么key1与key2一定不相等

④一个hash值可以对应多个键值(哈希冲突) 

四、哈希函数的方法

1. 直接定址法

        取关键字本身 / 关键字的某个线性函数值作为哈希地址。

        hash(key)= key 或者 hash(key)= a * key + b

2.除留余数法

        假设哈希表的表长为 m ,取一个不大于 m 但接近或等于 m 的质数 p ,利用取模运算,将关键值转化为哈希地址(取质数可以尽量避免冲突)

        hash(key)= key % p

3.平方取中法

        先通过关键值平方的方式扩大相近数之间的差别,然后根据长度取关键值平方值的中间几位数作为哈希地址

        hash(key)= ( key * key )/ 100 % 1000  // 先计算平方,去除末尾两位数,再取最后三位数(即取中间三位数作为哈希地址)

4.基数转换法

        将关键字看成另一种进制的数再转化为原来进制的数,选其中几位作为哈希地址

五、哈希冲突

         不同的关键字通过同一个哈希函数可能得到同一哈希地址,即 key1!=key2 而 hash(key1)== hash(key2)

当出现哈希冲突时,才用以下两种方法解决哈希冲突

        1.开放地址法

        将哈希表中的(空地址)向处理冲突开放,当哈希表未满时,处理冲突时需要尝试另外的单元,直到找到空的单元为止

        发生冲突时,开放地址法按照下面方法求得新的哈希地址:H(i)= (hash(key)+ F (i) ) % m

如果H(1) 仍发生哈希冲突,则再一次通过上述操作处理出 H (2)  ……直至 H (x) 不出现冲突 

关于F(x)的计算:

        ①线性探测法:即 F(i)=i

        ②二次探测法:F(i)=1^2, -1^2, 2^2, -2^2……i^2,-i^2

        ③伪随机数序列:F(i)=rand()

        2.链地址法

        将具有相同哈希地址的元素(或记录)存储在同一个线性链表

        思想:将键值通过哈希函数得到的值存储入哈希表中,当出现哈希冲突时,采用链表的方法储存相同哈希值对应的键值。

        1.每次插入键值时,最好插入表头(时间复杂度最低)

        2.查询关键值时,通过哈希函数计算出对应的哈希地址 i ,然后在对应的链表上扫描一遍即可

  • 18
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
哈希表是一种基于哈希函数进行快速查找的数据结构,它通过把关键码映射到表中一个位置来访问记录,以加快查找的速度。哈希表的设计思路如下: 1. 哈希函数的设计:哈希函数是哈希表的核心,它将关键字映射到哈希表中的位置。一个好的哈希函数应该具有以下特点: - 映射范围广:哈希函数应该将关键字均匀地映射到哈希表中的位置,避免出现大量的哈希冲突。 - 计算速度快:哈希函数的计算速度应该尽可能快,以提高哈希表的访问速度。 - 低冲突率:哈希函数应该尽可能地避免哈希冲突,以提高哈希表的访问效率。 2. 哈希冲突的解决:由于哈希函数的映射范围是有限的,所以不同的关键字可能会映射到同一个位置,这就是哈希冲突。哈希冲突的解决方法有以下两种: - 链地址法:将哈希表中的每个位置都连接一个链表,当发生哈希冲突时,将新的关键字插入到链表的末尾。 - 开放地址法:当发生哈希冲突时,通过某种算法找到哈希表中的下一个空位置,将新的关键字插入到该位置。 3. 哈希表的增删查改操作:哈希表的增删查改操作都需要先通过哈希函数找到关键字在哈希表中的位置,然后再进行相应的操作。具体操作如下: - 插入操作:将新的关键字插入到哈希表中的对应位置,如果发生哈希冲突,则按照链地址法或开放地址法进行解决。 - 删除操作:将关键字从哈希表中对应位置删除,如果该位置上有链表,则需要遍历链表找到对应的关键字进行删除。 - 查找操作:通过哈希函数找到关键字在哈希表中的位置,如果该位置上有链表,则需要遍历链表找到对应的关键字进行查找。 - 修改操作:通过哈希函数找到关键字在哈希表中的位置,如果该位置上有链表,则需要遍历链表找到对应的关键字进行修改。 下面是一个使用链地址法实现的哈希表的Python代码示例: ```python class ListNode: def __init__(self, key=None, value=None): self.key = key self.value = value self.next = None class MyHashMap: def __init__(self): self.size = 1000 self.table = [None] * self.size def _hash(self, key): return key % self.size def put(self, key, value): index = self._hash(key) if not self.table[index]: self.table[index] = ListNode(key, value) else: node = self.table[index] while node: if node.key == key: node.value = value return if not node.next: break node = node.next node.next = ListNode(key, value) def get(self, key): index = self._hash(key) node = self.table[index] while node: if node.key == key: return node.value node = node.next return -1 def remove(self, key): index = self._hash(key) node = prev = self.table[index] if not node: return if node.key == key: self.table[index] = node.next else: node = node.next while node: if node.key == key: prev.next = node.next break node, prev = node.next, prev.next ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值