数据结构与算法 哈希表

简介: 数据结构与算法 哈希表

常见的哈希表操作包括查询、添加键值对、删除键值对和遍历哈希表等。

基于数组实现

class Pair:
    def __init__(self, key, value) -> None:
        self.key = key
        self.value = value
  
  
  
class Array_Hash:
    def __init__(self):
        self.buckets = [None]*100
        for i in range(100):
            self.buckets[i] = []
    def hash_func(self, key):
        return key % 100
    def put(self, key, value):
        pair = Pair(key=key, value=value)
        index = self.hash_func(key)
        if self.buckets[index] == None:
            self.buckets[index] = []
        self.buckets[index].append(pair)
  
    def get(self, key):
        index = self.hash_func(key)
        lst = self.buckets[index]
        for pair in lst:
            if pair.key == key:
                return pair.value
        raise ValueError('没有这个键')
    def remove(self, key):
        index = self.hash_func(key)
        lst = self.buckets[index]
        for ix, pair in enumerate(lst):
            if pair.key == key:
                break
        del lst[ix]
    def entry_set(self):
        pair_list = []
        for bucket in self.buckets:
            for pair in bucket:
                pair_list.append(pair)
        return pair_list
    def key_set(self):
        key_list = []
        pair_list = self.entry_set()
        for pair in pair_list:
            key_list.append(pair.key)
        return key_list
    def value_set(self):
        value_list = []
        pair_list = self.entry_set()
        for pair in pair_list:
            value_list.append(pair.value)
        return value_list
    def print_hash(self):
        buckets = self.buckets
        for ix, bucket in enumerate(buckets):
            if bucket != []:
                print(ix, end='  ---   ')
                for pair in bucket:
                    print(pair.key, "->", pair.value, end=' >>> ')
                print('结束')

基于链表实现

class ListNode:
    def __init__(self, key, value) -> None:
        self.key = key
        self.value = value
        self.next = None
  
class ListHash:
    def __init__(self) -> None:
        self.buckets = [None] * 100
    def hash_func(self, key):
        return key % 100
    def put(self, key, value):
        node = ListNode(key, value)
        index = self.hash_func(key)
        if self.buckets[index] == None:
            self.buckets[index] = node
        else:
            original_node = self.buckets[index]
            while original_node.next:
                original_node = original_node.next
            original_node.next = node
  
    def get(self, key):
        index = self.hash_func(key)
        bucket = self.buckets[index]
        while bucket:
            if bucket.key == key:
                return bucket.value
            else:
                bucket = bucket.next
        raise IndexError('hash没有这个键')
  
    def remove(self, key):
        index = self.hash_func(key)
        bucket = self.buckets[index]
        while bucket:
            if bucket.next != None:
                if bucket.next.key == key:
                    remove_node = bucket.next
                    bucket.next = remove_node.next
                    remove_node.next = None
                    break
            bucket = bucket.next
  
    def entry_set(self):
        lst = []
        for bucket in self.buckets:
            if bucket != None:
                lst.append(bucket)
        return lst
  
    def key_set(self):
        lst = []
        listnodes = self.entry_set()
        for listnode in listnodes:
            while listnode:
                lst.append(listnode.key)
                listnode = listnode.next
        return lst
    def value_set(self):
        lst = []
        listnodes = self.entry_set()
        for listnode in listnodes:
            while listnode:
                lst.append(listnode.value)
                listnode = listnode.next
        return lst
    def print_hash(self):
        for ix, bucket in enumerate(self.buckets):
            if bucket:
                print(ix, end='   ---   ')
                while bucket:
                    print(bucket.key, "->", bucket.value, end=' >>> ')
                    bucket = bucket.next
                print('结束')

进一步优化

当链表很长时,查询效率 𝑂(𝑛) 很差。此时可以将链表转换为“AVL 树”或“红黑树”,从而将查询操作的时间复杂度优化至 𝑂(log 𝑛)


哈希算法目标

哈希算法特点

  • 确定性:对于相同的输入,哈希算法应始终产生相同的输出。这样才能确保哈希表是可靠的。
  • 效率高:计算哈希值的过程应该足够快。计算开销越小,哈希表的实用性越高。
  • 均匀分布:哈希算法应使得键值对平均分布在哈希表中。分布越平均,哈希冲突的概率就越低。
    实际上,哈希算法除了可以用于实现哈希表,还广泛应用于其他领域中。
  • 密码存储:为了保护用户密码的安全,系统通常不会直接存储用户的明文密码,而是存储密码的哈希值。当用户输入密码时,系统会对输入的密码计算哈希值,然后与存储的哈希值进行比较。如果两者匹配,那么密码就被视为正确。
  • 数据完整性检查:数据发送方可以计算数据的哈希值并将其一同发送;接收方可以重新计算接收到的数据的哈希值,并与接收到的哈希值进行比较。如果两者匹配,那么数据就被视为完整的。
    对于密码学的相关应用,为了防止从哈希值推导出原始密码等逆向工程,哈希算法需要具备更高等级的安全特性。
  • 抗碰撞性:应当极其困难找到两个不同的输入,使得它们的哈希值相同。
  • 雪崩效应:输入的微小变化应当导致输出的显著且不可预测的变化。

哈希算法的设计

  • 加法哈希:对输入的每个字符的 ASCII 码进行相加,将得到的总和作为哈希值。
def add_hash(key: str) -> int:
    hash = 0
    modulus = 1000000007
    for c in key:
        hash += ord(c)
    return hash % modulus
  • 乘法哈希:利用了乘法的不相关性,每轮乘以一个常数,将各个字符的 ASCII 码累积到哈希值中。
def mul_hash(key: str) -> int:
    hash = 0
    modulus = 1000000007
    for c in key:
        hash = 31 * hash + ord(c)
    return hash % modulus
  • 异或哈希:将输入数据的每个元素通过异或操作累积到一个哈希值中。
def xor_hash(key: str) -> int:
    hash = 0
    modulus = 1000000007
    for c in key:
        hash ^= ord(c)
    return hash % modulus
  • 旋转哈希:将每个字符的 ASCII 码累积到一个哈希值中,每次累积之前都会对哈希值进行旋转操作。
def rot_hash(key: str) -> int:
    hash = 0
    modulus = 1000000007
    for c in key:  
        hash = (hash << 4) ^ (hash >> 28) ^ ord(c)
    return hash % modulus

对大质数 1000000007 取模,避免约分导致扎堆

![[Pasted image 20230919222910.png]]

重点回顾

  • 输入 key ,哈希表能够在 𝑂(1) 时间内查询到 value ,效率非常高。
  • 常见的哈希表操作包括查询、添加键值对、删除键值对和遍历哈希表等。
  • 哈希函数将 key 映射为数组索引,从而访问对应桶并获取 value 。
  • 两个不同的 key 可能在经过哈希函数后得到相同的数组索引,导致查询结果出错,这种现象被称为哈希冲突。
  • 哈希表容量越大,哈希冲突的概率就越低。因此可以通过扩容哈希表来缓解哈希冲突。与数组扩容类似,哈希表扩容操作的开销很大。
  • 负载因子定义为哈希表中元素数量除以桶数量,反映了哈希冲突的严重程度,常用作触发哈希表扩容的条件。
  • 链式地址通过将单个元素转化为链表,将所有冲突元素存储在同一个链表中。然而,链表过长会降低查询效率,可以进一步将链表转换为红黑树来提高效率。
  • 开放寻址通过多次探测来处理哈希冲突。线性探测使用固定步长,缺点是不能删除元素,且容易产生聚集。多次哈希使用多个哈希函数进行探测,相较线性探测更不易产生聚集,但多个哈希函数增加了计算量。
  • 不同编程语言采取了不同的哈希表实现。例如,Java 的 HashMap 使用链式地址,而 Python 的 Dict 采用开放寻址。在哈希表中,我们希望哈希算法具有确定性、高效率和均匀分布的特点。在密码学中,哈希算法还应该具备抗碰撞性和雪崩效应。
  • 哈希算法通常采用大质数作为模数,以最大化地保证哈希值的均匀分布,减少哈希冲突。
  • 常见的哈希算法包括 MD5、SHA‑1、SHA‑2 和 SHA3 等。MD5 常用于校验文件完整性,SHA‑2 常用于安全应用与协议。
  • 编程语言通常会为数据类型提供内置哈希算法,用于计算哈希表中的桶索引。通常情况下,只有不可变对象是可哈希的。


目录
相关文章
|
1月前
|
存储 算法 数据处理
公司局域网管理中的哈希表查找优化 C++ 算法探究
在数字化办公环境中,公司局域网管理至关重要。哈希表作为一种高效的数据结构,通过哈希函数将关键值(如IP地址、账号)映射到数组索引,实现快速的插入、删除与查找操作。例如,在员工登录验证和设备信息管理中,哈希表能显著提升效率,避免传统线性查找的低效问题。本文以C++为例,展示了哈希表在局域网管理中的具体应用,包括设备MAC地址与IP分配的存储与查询,并探讨了优化哈希函数和扩容策略,确保网络管理高效准确。
|
3月前
|
存储 算法 安全
探究‘公司禁用 U 盘’背后的哈希表算法与 Java 实现
在数字化办公时代,信息安全至关重要。许多公司采取“禁用U盘”策略,利用哈希表算法高效管理外接设备的接入权限。哈希表通过哈希函数将设备标识映射到数组索引,快速判断U盘是否授权。例如,公司预先将允许的U盘标识存入哈希表,新设备接入时迅速验证,未授权则禁止传输并报警。这有效防止恶意软件和数据泄露,保障企业信息安全。 代码示例展示了如何用Java实现简单的哈希表,模拟公司U盘管控场景。哈希表不仅用于设备管理,还在文件索引、用户权限等多方面助力信息安全防线的构建,为企业数字化进程保驾护航。
|
15天前
|
存储 监控 算法
员工行为监控软件中的 Go 语言哈希表算法:理论、实现与分析
当代企业管理体系中,员工行为监控软件已逐步成为维护企业信息安全、提升工作效能的关键工具。这类软件能够实时记录员工操作行为,为企业管理者提供数据驱动的决策依据。其核心支撑技术在于数据结构与算法的精妙运用。本文聚焦于 Go 语言中的哈希表算法,深入探究其在员工行为监控软件中的应用逻辑与实现机制。
55 14
|
12天前
|
存储 监控 算法
基于 Python 哈希表算法的局域网网络监控工具:实现高效数据管理的核心技术
在当下数字化办公的环境中,局域网网络监控工具已成为保障企业网络安全、确保其高效运行的核心手段。此类工具通过对网络数据的收集、分析与管理,赋予企业实时洞察网络活动的能力。而在其运行机制背后,数据结构与算法发挥着关键作用。本文聚焦于 PHP 语言中的哈希表算法,深入探究其在局域网网络监控工具中的应用方式及所具备的优势。
44 7
|
16天前
|
存储 监控 算法
基于 C++ 哈希表算法的局域网如何监控电脑技术解析
当代数字化办公与生活环境中,局域网的广泛应用极大地提升了信息交互的效率与便捷性。然而,出于网络安全管理、资源合理分配以及合规性要求等多方面的考量,对局域网内计算机进行有效监控成为一项至关重要的任务。实现局域网内计算机监控,涉及多种数据结构与算法的运用。本文聚焦于 C++ 编程语言中的哈希表算法,深入探讨其在局域网计算机监控场景中的应用,并通过详尽的代码示例进行阐释。
37 4
|
18天前
|
存储 监控 算法
单位电脑监控软件中 PHP 哈希表算法的深度剖析与理论探究
数字化办公的时代背景下,单位电脑监控软件已成为企业维护信息安全、提升工作效率的关键工具。此类软件可全面监测员工的电脑操作行为,收集海量数据,故而高效管理和处理这些数据显得尤为重要。数据结构与算法在此过程中发挥着核心作用。本文将聚焦于哈希表这一在单位电脑监控软件中广泛应用的数据结构,并通过 PHP 语言实现相关功能,为优化单位电脑监控软件提供技术支持。
36 3
|
24天前
|
存储 监控 算法
论内网电脑监控软件中 PHP 哈希表算法的深度剖析与探究
当代企业网络管理体系中,内网电脑监控软件占据着关键地位。其功能涵盖对员工电脑操作行为的实时监测,以此维护企业信息安全,同时助力企业优化网络资源配置,提升整体工作效能。在构建内网电脑监控软件的诸多技术中,数据结构与算法构成了核心支撑体系。本文聚焦于哈希表这一重要数据结构,深入剖析其在 PHP 语言环境下,如何为内网电脑监控软件的高效运作提供助力,并通过详实的代码示例予以阐释。
36 3
|
1月前
|
存储 监控 算法
基于 Python 哈希表算法的员工上网管理策略研究
于当下数字化办公环境而言,员工上网管理已成为企业运营管理的关键环节。企业有必要对员工的网络访问行为予以监控,以此确保信息安全并提升工作效率。在处理员工上网管理相关数据时,适宜的数据结构与算法起着举足轻重的作用。本文将深入探究哈希表这一数据结构在员工上网管理场景中的应用,并借助 Python 代码示例展开详尽阐述。
43 3
|
1月前
|
存储 NoSQL Java
【数据结构进阶】哈希表
哈希表是一种高效的数据结构,通过哈希函数实现数据映射,支持平均O(1)时间复杂度的查找、插入和删除操作。本文详细介绍了哈希表的基本概念、哈希函数的设计(如直接定址法和除留余数法)以及哈希冲突的解决方法(如开放定址法和链地址法)。同时,文章通过代码实例展示了线性探测和链地址法两种哈希表的实现过程,并分析了各自的优缺点。最后总结指出,合理选择哈希函数和冲突解决策略是优化哈希表性能的关键。
77 2
|
1月前
|
存储 算法 文件存储
探秘文件共享服务之哈希表助力 Python 算法实现
在数字化时代,文件共享服务不可或缺。哈希表(散列表)通过键值对存储数据,利用哈希函数将键映射到特定位置,极大提升文件上传、下载和搜索效率。例如,在大型文件共享平台中,文件名等信息作为键,物理地址作为值存入哈希表,用户检索时快速定位文件,减少遍历时间。此外,哈希表还用于文件一致性校验,确保传输文件未被篡改。以Python代码示例展示基于哈希表的文件索引实现,模拟文件共享服务的文件索引构建与检索功能。哈希表及其分布式变体如一致性哈希算法,保障文件均匀分布和负载均衡,持续优化文件共享服务性能。