简单讲解哈希表

哈希表(Hash Table),也被称为散列表,是一种高效的数据结构,它可以在O(1)的时间复杂度下完成插入、删除、查找等基本操作。哈希表是通过将关键字映射到一个固定大小的表中来实现的,这个映射函数被称为哈希函数。

什么是哈希函数

哈希函数是将任意长度的输入值(也称为“键”或“关键字”)映射为固定大小的输出值(也称为“哈希值”或“散列”)。哈希函数必须将不同的关键字映射到不同的哈希值中,从而使得关键字之间的比较可以转化为哈希值之间的比较,提高了查找效率。

常用的哈希函数有以下几种:

  1. 直接取模法:对哈希表的大小(通常为素数)取模,取模的结果作为哈希值。直接取模法的缺点是可能会使得某些哈希值的分布不均匀,影响了性能。
  2. 加权取模法:将关键字的每一位乘以不同的权值,再将所有结果相加,最后对哈希表的大小取模,取模的结果作为哈希值。加权取模法可以解决直接取模法产生的哈希冲突问题。
  3. MD5和SHA1:基于MD5和SHA1算法的哈希函数,可以生成128位和160位哈希值,具有较高的安全性和哈希性能。

哈希表的实现

哈希表的实现主要包含两个部分:哈希函数和哈希冲突的解决方法。

哈希函数

哈希函数的选择决定了哈希表的性能,好的哈希函数可以使哈希值的分布较为均匀,从而减少哈希冲突的概率。常用的哈希函数如下:

def hash_function(key, size):
    """
    直接取模法哈希函数
    :param key: 关键字
    :param size: 哈希表的大小
    :return: 哈希值
    """
    return key % size

哈希冲突的解决方法

哈希冲突指的是不同的关键字映射到同一个哈希值的情况。常用的哈希冲突解决方法有以下几种:

  1. 开放地址法:当出现哈希冲突时,依次查找下一个空的哈希桶,直到找到为止。
  2. 链地址法:将哈希桶中的元素存储在一个链表中,当出现哈希冲突时,在链表的末尾添加一个新元素。

哈希表的操作

插入操作

插入操作包含以下步骤:

  1. 计算关键字的哈希值;
  2. 根据哈希值找到对应的哈希桶;
  3. 判断哈希桶是否为空,如果为空,直接插入元素;
  4. 如果哈希桶不为空,根据哈希冲突的解决方法,找到下一个空闲的哈希桶,插入元素。
def insert(hash_table, key, value):
    # 计算哈希值
    hash_value = hash_function(key, len(hash_table))
    # 找到对应的哈希桶
    bucket = hash_table[hash_value]
    # 插入元素
    if not bucket:
        hash_table[hash_value] = [(key, value)]
    else:
        for i in range(len(bucket)):
            if bucket[i][0] == key:
                bucket[i] = (key, value)
                break
        else:
            bucket.append((key, value))

删除操作

删除操作比插入操作稍微复杂一些,因为需要考虑到哈希冲突。

删除操作包含以下步骤:

  1. 计算关键字的哈希值;
  2. 根据哈希值找到对应的哈希桶;
  3. 在哈希桶中查找是否存在关键字对应的元素;
  4. 如果存在,删除元素,如果不存在,返回错误提示。
def delete(hash_table, key):
    # 计算哈希值
    hash_value = hash_function(key, len(hash_table))
    # 找到对应的哈希桶
    bucket = hash_table[hash_value]
    # 在哈希桶中查找元素
    if bucket:
        for i in range(len(bucket)):
            if bucket[i][0] == key:
                del bucket[i]
                return
    print(f"Key {key} not found.")

查找操作

查找操作和删除操作类似,也需要考虑到哈希冲突。

查找操作包含以下步骤:

  1. 计算关键字的哈希值;
  2. 根据哈希值找到对应的哈希桶;
  3. 在哈希桶中查找是否存在关键字对应的元素;
  4. 如果存在,返回对应的值,如果不存在,返回错误提示。
def search(hash_table, key):
    # 计算哈希值
    hash_value = hash_function(key, len(hash_table))
    # 找到对应的哈希桶
    bucket = hash_table[hash_value]
    # 在哈希桶中查找元素
    if bucket:
        for i in range(len(bucket)):
            if bucket[i][0] == key:
                return bucket[i][1]
    print(f"Key {key} not found.")

示例说明

示例一

假设我们需要存储学生的姓名和对应的成绩信息,我们可以选择使用哈希表来实现。以下是实现的代码:

hash_table = [None] * 100

def add_student(name, score):
    insert(hash_table, name, score)

def get_score(name):
    return search(hash_table, name)

在上面的代码中,我们使用了一个长度为100的哈希表来存储学生信息,每个元素的格式为(key, value),其中key为学生的姓名,value为对应的成绩。我们通过调用insert函数来向哈希表中添加学生信息,通过调用search函数来查找学生信息。

示例二

假设我们需要存储一些网站的URL地址和对应的IP地址信息,我们可以选择使用哈希表来实现。以下是实现的代码:

hash_table = [None] * 100

def add_url(url, ip):
    insert(hash_table, url, ip)

def get_ip(url):
    return search(hash_table, url)

在上面的代码中,我们使用了一个长度为100的哈希表来存储URL地址和对应的IP地址信息,每个元素的格式为(key, value),其中key为URL地址,value为对应的IP地址。我们通过调用insert函数来向哈希表中添加URL地址和对应的IP地址信息,通过调用search函数来查找URL对应的IP地址。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:简单讲解哈希表 - Python技术站

(0)
上一篇 2023年5月17日
下一篇 2023年5月17日

相关文章

  • 带你了解Java数据结构和算法之前缀,中缀和后缀表达式

    带你了解Java数据结构和算法之前缀、中缀和后缀表达式 1. 前缀表达式(Prefix Expression) 前缀表达式是指运算符位于操作数之前的表达式,也被称为波兰式。前缀表达式的优点在于,每个运算符的优先级都可以通过括号来明确,不需要考虑运算符的优先级。同时,整个表达式的意义也可以很清晰地传达。 举个例子,下面是一个前缀表达式: + * 4 5 6 /…

    数据结构 2023年5月17日
    00
  • CSP-何以包邮?

    题目描述 新学期伊始,适逢顿顿书城有购书满 x 元包邮的活动,小 P 同学欣然前往准备买些参考书。一番浏览后,小 P 初步筛选出 n 本书加入购物车中,其中第 i 本(1≤i≤n)的价格为 ai 元。考虑到预算有限,在最终付款前小 P 决定再从购物车中删去几本书(也可以不删),使得剩余图书的价格总和 m 在满足包邮条件(m≥x)的前提下最小。 试帮助小 P …

    算法与数据结构 2023年5月11日
    00
  • Java数据结构专题解析之栈和队列的实现

    Java数据结构专题解析之栈和队列的实现 什么是栈和队列? 在计算机科学中,栈(Stack)和队列(Queue)都是常见的数据结构,用于解决许多问题。它们都是线性数据结构,但它们的元素访问顺序不同。 栈是先进后出(Last In First Out,LIFO)的结构,即最后放入栈中的元素最先被访问。 队列是先进先出(First In First Out,FI…

    数据结构 2023年5月17日
    00
  • C语言数据结构与算法之排序总结(二)

    C语言数据结构与算法之排序总结(二) 本篇文章是关于C语言数据结构与算法中排序算法的详细讲解,涉及了八种排序算法。 冒泡排序(Bubble Sort) 冒泡排序是一种简单的排序算法。在排序过程中,它会重复地交换相邻的元素,这是它名称的由来。 示例代码: c void bubble_sort(int arr[], int n) { for (int i = 0…

    数据结构 2023年5月17日
    00
  • Java数据结构与算法学习之循环链表

    Java数据结构与算法学习之循环链表 本文将详细介绍Java数据结构中的一种链表类型——循环链表,并讲解如何使用Java实现循环链表。同时,本文也提供了两个示例,方便读者更好地理解和运用循环链表。 什么是循环链表 循环链表是一种链表,它与单向链表和双向链表不同之处在于它的最后一个结点指向第一个结点。这就形成了一个循环链,因此称之为循环链表。 如何实现循环链表…

    数据结构 2023年5月17日
    00
  • Java集合和数据结构排序实例详解

    Java集合和数据结构排序实例详解 作为Java程序员,集合和数据结构是我们经常会用到的工具,其中排序是其中非常重要的一环。本文将为大家详细介绍Java中集合和数据结构排序的实例。 Java集合排序 在Java中,集合排序通常使用Collections工具类来完成。Collections提供了多种排序算法,包括插入排序、选择排序、归并排序等等。例如,下面的示…

    数据结构 2023年5月17日
    00
  • Java数据结构之List的使用总结

    非常感谢您对本网站的关注。Java数据结构之List的使用总结是一个非常重要的主题,这里将为您详细介绍。 1. List是什么 在Java中,List是一种非常实用的数据结构,它代表了一个元素的有序集合,其中的每个元素都可以用一个整数索引来标识。List允许多个元素重复,同时还可以在集合的任意位置插入或者删除元素。 Java中的List主要分为两类:Arra…

    数据结构 2023年5月17日
    00
  • C语言编程数据结构的栈和队列

    C语言编程数据结构的栈和队列 什么是栈 栈(Stack) 是限定仅在表尾进行插入和删除操作的线性表。栈也称为后进先出( Last In First Out)的线性表,简称 LIFO 结构。栈结构有两个最重要的操作:入栈和出栈。其中,入栈操作向栈中添加一个元素,出栈操作从栈中删除一个元素。 栈的基本操作 初始化栈 入栈 出栈 取栈顶元素 判空 判满 // 栈的…

    数据结构 2023年5月17日
    00
合作推广
合作推广
分享本页
返回顶部