哈希表相关

哈希函数

散列函数(Hash Function)又名哈希函数,是计算机科学中一个重要的课题。什么是散列函数呢?其实,这个概念并没有一个严格的定义。一般说来,散列函数满足以下的条件:

1、对输入值运算,得到一个固定长度的摘要(Hash value);

2、不同的输入值可能对应同样的输出值;

     不过,仅仅满足上面这两条的函数,作为散列函数,还有不足的地方。我们还希望散列函数满足下面几点:

        1、散列函数的输出值尽量接近均匀分布;

        2、x的微小变化可以使f(x)发生非常大的变化,即所谓“雪崩效应”

上面两点用数学语言表示,就是:

1、输出值y的分布函数F(y)=y/m, m为散列函数的最大值。或记为y~U[0, m]

2、|df(x)/dx| >> 1;

哈希冲突的处理

在Hash表的建立时,会发生Hash值冲突的情况。实际上,如果记录Hash值的范围多于Hash表的条数,根据抽屉原理,一定会发生冲突。对于冲突的处理,我们一般有这几种方法:

  1. 对Hash表中每个Hash值建立一个冲突表,即将冲突的几个记录以表的形式存储在其中;
  2. 改变规则重新计算一次Hash值;
  3. 建立一个公用的区域存放冲突的表项;

在工程上,考虑到实现算法的复杂度,方法1用得是最多的。对于方法1,又有两种不同的实现,一种方法是对每个Hash值,建立一个Hash桶(Bucket),桶的容量是固定的,也就是只能处理固定次数的冲突,如1048576个Hash桶,每个桶中有4个表项(Entry),总计4M个表项。另一种方法是,不限制Hash桶的容量,以链表形式将冲突的记录挂接在一个Hash桶中。

这两种实现各有什么利弊呢?首先,让我们看看第一种实现:

在这种情况下,由于Hash桶容量的限制,所以,有可能发生Hash表填不满的情况,也就是,虽然Hash表里面还有空位,但是新建的表项由于冲突过多,而不能装入Hash表中。不过,这样的实现也有其好处,就是查表的最大开销是可以确定的,因为最多处理的冲突数是确定的,所以算法的时间复杂度为O(1)+O(m),其中m为Hash桶容量。

而另一种实现,由于Hash桶的容量是无限的,因此,只要没有超出Hash表的最大容量,就能够容纳新建的表项。但是,一旦发生了Hash冲突严重的情况,就会造成Hash桶的链表过长,大大降低查找效率。在最坏的情况下,时间复杂度退化为O(n),其中n为Hash表的总容量。当然,这种情况的概率小之又小,几乎是可以忽略的。

Hash表的一个应用例子,是在网关(Gateway)中。以网络防火墙为例,它是根据源IP,目的IP,源端口,目的端口,协议号构成的五元组来标识一条网络数据流的,并且根据五元组来建立会话表项(session entry)。为了查找便捷,一般都使用Hash表来实现这个会话表,以提高转发的效率。事实上,对于大量表项的查找,逐项查找是不允许的,一般都使用Hash表来实现。

  • C++  STL :unordered_map/unordered_set了解一下^_^,详细介绍参考:http://www.nowamagic.net/academy/detail/3008050

### 哈希表编程练习题及相知识点 #### 使用哈希表的经典算法问题 以下是几个经典的涉及哈希表的数据结构和算法题目: 1. **快乐数判断** 判断一个数是否为快乐数可以通过哈希表实现。通过维护一个集合 `seen` 来记录已经出现的数字,防止无限循环的发生[^2]。 ```python class Solution: def isHappy(self, n): seen = set() while n != 1 and n not in seen: seen.add(n) n = sum(int(i) ** 2 for i in str(n)) return n == 1 ``` 2. **两数之和 (Two Sum)** 这是一个非常典型的哈希表应用问题。给定一个整数数组 `nums` 和目标值 `target`,找出数组中两个数使得它们相加为目标值并返回其索引。 解决方法是利用字典存储遍历过程中遇到的数值及其对应的下标位置,从而可以在 O(1) 时间复杂度内完成查询操作。 ```python def twoSum(nums, target): hash_map = {} for index, num in enumerate(nums): complement = target - num if complement in hash_map: return [hash_map[complement], index] hash_map[num] = index ``` 3. **有效的字母异位词 (Valid Anagram)** 验证两个字符串是否互为字母异位词(即由相同字符组成的同排列)。此问题可通过计数的方式解决,而最高效的方法之一就是借助哈希表统计每个字符出现次数。 ```python from collections import Counter def isAnagram(s: str, t: str) -> bool: return Counter(s) == Counter(t) ``` 4. **第一个唯一字符 (First Unique Character In A String)** 找到字符串中第一个重复的字符,并返回它的索引。如果没有这样的字符,则返回 `-1`。该问题也可以采用哈希表来记录各字符频率后再扫描一次原串找到符合条件的结果。 ```python def firstUniqChar(s: str) -> int: count = {} for char in s: count[char] = count.get(char, 0) + 1 for idx, char in enumerate(s): if count[char] == 1: return idx return -1 ``` 5. **最长无重复子序列长度 (Longest Substring Without Repeating Characters)** 动态规划配合滑动窗口技术以及辅助使用的哈希表能够很好地处理此类连续区间内的约束条件优化求解过程。 --- #### 符号表管理中的实际应用场景 除了上述竞赛类题目外,在真实世界软件开发场景里也广泛存在对于哈希表的需求实例——比如编译器内部会运用它构建符号表以加速源码解析阶段的工作效率提升[^3]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值