简单讲解哈希表

哈希表(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日

相关文章

  • C语言链表案例学习之通讯录的实现

    让我详细讲解一下“C语言链表案例学习之通讯录的实现”的完整攻略。 1. 案例简介 本案例的目的是通过实现一个简单的通讯录程序,来学习C语言链表的原理和操作。程序主要功能涵盖通讯录添加、删除、修改以及查询。 2. 程序架构 程序的整体结构如下所示: 头文件声明 结构体定义 函数声明 主函数 函数实现 其中,头文件声明包含stdio.h、stdlib.h以及st…

    数据结构 2023年5月17日
    00
  • C语言数据结构 快速排序实例详解

    C语言数据结构 快速排序实例详解 什么是快速排序? 快速排序(Quicksort)是一种采用分治法(Divide and Conquer)的排序算法,通过将一个大问题逐步分解为小问题来解决的一种工具。 快速排序是一个比较快的排序算法,在平均状况下,排序n个项目要 O(n log n) 次比较,最坏情况下需要O(n^2)次比较,但这种状况并不常见。 快速排序算…

    数据结构 2023年5月17日
    00
  • [Week 19]每日一题(C++,数学,并查集,动态规划)

    目录 [Daimayuan] T1 倒数第n个字符串(C++,进制) 输入格式 输出格式 样例输入 样例输出 解题思路 [Daimayuan] T2 排队(C++,并查集) 输入格式 输出格式 样例输入1 样例输出1 样例输入2 样例输出2 样例输入3 样例输出3 数据规模 解题思路 [Daimayuan] T3 素数之欢(C++,BFS) 数据规模 输入格…

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

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

    数据结构 2023年5月17日
    00
  • C语言编程简单却重要的数据结构顺序表全面讲解

    C语言编程简单却重要的数据结构顺序表全面讲解 什么是顺序表? 顺序表是一种线性表,指的是一组有限元素的有限序列,其元素的逻辑顺序与它们在分配到的内存地址上的物理顺序相同或者等价。也就是说,顺序表中的元素按照其在内存中的位置依次存放。 顺序表的实现方式 顺序表的实现方式一般是使用数组,数组中的每一个元素对应着顺序表中的一个元素,位置相对应。 顺序表的优点 支持…

    数据结构 2023年5月17日
    00
  • C++线性表深度解析之动态数组与单链表和栈及队列的实现

    C++线性表深度解析之动态数组与单链表和栈及队列的实现 动态数组的实现 动态数组是一种可以动态扩展的数组结构,它的容量可以随着需要而动态增加。在C++中,使用vector类可以实现动态数组的功能。vector类相当于动态分配了一块内存空间,在使用时可以根据需要进行动态扩展。下面是一个示例代码: #include <vector> #include…

    数据结构 2023年5月17日
    00
  • c语言 数据结构实现之字符串

    下面是详细讲解“c语言 数据结构实现之字符串”的完整攻略。 1. 什么是字符串? 字符串是由一组字符组成的序列,字符可以是字母、数字、标点符号等,字符串常用于文本处理。 在C语言中,字符串是以‘\0’ 结束的字符数组。 2. 字符串的常见操作 常见的字符串操作包括:复制、比较、连接、查找等。 2.1 字符串复制 字符串复制是将一个字符串的内容复制到另一个字符…

    数据结构 2023年5月17日
    00
  • Java数据结构之常见排序算法(上)

    Java数据结构之常见排序算法(上) 本篇文章将介绍常见的排序算法,包括冒泡排序、选择排序、插入排序、快速排序和归并排序。这些排序算法既是学习算法和数据结构的入门知识,也是在实际工作中常用的基础算法。 冒泡排序 冒泡排序是一种简单的排序算法,它的基本思想是从前往后依次比较相邻的两个元素,如果前面的元素比后面的元素大,则交换它们的位置,重复这个过程,每一轮比较…

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