跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C++算法

哈希算法基础:原理、函数与哈希表实现

哈希算法将任意长度数据映射为固定长度值,具有确定性、高效性、离散性及特定场景下的不可逆性。经典哈希函数包括简单取模、加密哈希(如 SHA-256)及非加密哈希(如 MurmurHash)。哈希表通过哈希函数实现键值对快速存取,平均时间复杂度 O(1),需处理哈希冲突,常用链地址法或开放地址法。哈希函数的基本实现、哈希表数据结构构建以及结合链表实现的 LRU 缓存策略,展示了哈希算法在数据存储与优化中的应用。

利刃发布于 2026/3/16更新于 2026/6/1628 浏览
哈希算法基础:原理、函数与哈希表实现

引言

哈希算法(Hashing Algorithm)是一种将复杂数据映射到简单空间的算法,它赋予了无序的世界以秩序,将分散的数据安排得井井有条。本文将探究它的原理、应用与局限。

哈希的本质

哈希算法的核心思想是将任意长度的数据映射到固定长度的值,称之为哈希值(Hash Value)或散列值。这个过程像是一场化繁为简的魔术,将庞杂的输入浓缩成一个小巧的'指纹'。这种'指纹'唯一性与固定性,使得哈希算法成为计算机科学中不可或缺的工具。

哈希函数(Hash Function)是实现这一魔法的核心,其关键特性包括:

  • 确定性:相同的输入总能生成相同的输出。
  • 高效性:计算哈希值的过程必须快速且轻量。
  • 离散性:尽可能避免不同的输入产生相同的输出(即哈希冲突)。
  • 不可逆性(特定场景下):某些场景需要保证从哈希值无法反推出原始输入。

这些特性赋予了哈希算法广泛的适用性,无论是数据存储、加密安全还是网络协议,哈希算法无处不在。

经典哈希函数

哈希算法的发展历程中,涌现出许多经典的哈希函数,每一种都为不同的场景提供了解决方案:

  1. 简单哈希函数:最简单的哈希函数基于数学取模(Modulo)的方式,例如 h(x)=x mod m。它适用于简单场景,例如将数据均匀分布到固定数量的桶中。然而,对于复杂的数据,这种方法可能导致大量冲突。
  2. 加法与乘法哈希函数:在更多场景中,结合数据的多个特征,通过加权或乘法的方式生成哈希值,例如 h(x)=(ax+b) mod m。这种方法能显著降低简单取模的冲突概率。
  3. 加密哈希算法(Cryptographic Hash Functions):如 MD5、SHA-1 和 SHA-256,这些算法旨在提供高安全性特性,广泛用于密码存储、数字签名和区块链技术。它们的特点是抗碰撞性和雪崩效应(输入的微小变化会显著改变输出)。
  4. 非加密哈希算法:如 MurmurHash 和 CityHash,它们不强调安全性,但在性能和冲突率上表现优异,常用于数据库和分布式系统。

哈希表实现

哈希算法最典型的应用场景是哈希表(Hash Table)。这是一个将键(Key)与值(Value)关联的数据结构,它通过哈希函数将键映射到数组的索引,实现快速的数据存取。

哈希表的操作:

  • 插入(Insert):通过哈希函数计算键的索引,将值存入数组。
  • 查找(Search):根据键计算索引,直接定位到存储值的位置。
  • 删除(Delete):查找到索引后删除对应的值。

哈希表的优点:

  • 时间复杂度为 O(1):无论插入还是查找,平均时间复杂度都极低。
  • 灵活性:支持动态数据存储,且键值对可以是任意类型。

然而,哈希表也面临哈希冲突的问题,即多个键可能映射到同一索引。解决冲突的常用方法包括链地址法和开放地址法。

哈希函数实现

哈希函数的核心目标是将任意输入映射为固定长度的输出值。一个简单的哈希函数示例如下:

#include <iostream>
#include <string>
using namespace std;

// 简单的哈希函数:字符求和并取模
int simpleHash(string key, int tableSize) {
    int hashValue = 0;
    for (char c : key) {
        hashValue += c; // 累加 ASCII 值
    }
    return hashValue % tableSize; // 取模以映射到哈希表大小
}

int main() {
    string key = "hash";
    int tableSize = 10;
    cout << "Hash value of \"" << key << "\": " << simpleHash(key, tableSize) << endl;
    return 0;
}

输出:

Hash value of 'hash': 9

代码解释:

  • simpleHash 是一个简单的哈希函数,它将字符串中的每个字符的 ASCII 值累加起来。
  • 然后通过取模操作,将累加结果映射到一个固定范围(哈希表的大小)。
  • 尽管简单,但这种方法容易引发哈希冲突,因为不同的输入可能映射到相同的哈希值。

哈希表实现

哈希表是一种数据结构,通过哈希函数快速定位存储值。以下是一个简单的哈希表插入和查找实现:

#include <iostream>
#include <vector>
#include <list>
#include <string>
using namespace std;

// 哈希表的定义
class HashTable {
private:
    vector<list<string>> table; // 使用链地址法解决冲突
    int tableSize;

    // 哈希函数
    int hashFunction(string key) {
        int hashValue = 0;
        for (char c : key) {
            hashValue += c;
        }
        return hashValue % tableSize;
    }

public:
    // 构造函数
    HashTable(int size) : tableSize(size) {
        table.resize(tableSize);
    }

    // 插入操作
    void insert(string key) {
        int index = hashFunction(key);
        table[index].push_back(key);
    }

    // 查找操作
    bool search(string key) {
        int index = hashFunction(key);
        for (string item : table[index]) {
            if (item == key) return true;
        }
        return false;
    }

    // 打印哈希表
    void display() {
        for (int i = 0; i < tableSize; i++) {
            cout << "Bucket " << i << ": ";
            for (string key : table[i]) {
                cout << key << " ";
            }
            cout << endl;
        }
    }
};

int main() {
    HashTable hashTable(5);
    hashTable.insert("hello");
    hashTable.insert("world");
    hashTable.insert("hash");
    hashTable.insert("table");
    hashTable.display();
    cout << "Search for 'world': " << (hashTable.search("world") ? "Found" : "Not Found") << endl;
    cout << "Search for 'data': " << (hashTable.search("data") ? "Found" : "Not Found") << endl;
    return 0;
}

输出:

Bucket 0: Bucket 1: table Bucket 2: Bucket 3: hello world hash Bucket 4: Search for 'world': Found Search for 'data': Not Found

代码解释:

  • 哈希函数:hashFunction 根据字符求和并取模,将键映射到一个固定范围。
  • 链地址法:当两个键映射到同一个索引时,将它们存储在该桶(Bucket)中的链表中,解决哈希冲突。
  • 插入操作:通过哈希函数计算键的索引,将键插入到对应桶中。
  • 查找操作:定位到桶后,遍历桶内的链表查找目标键。

实际应用:LRU 缓存

哈希表结合链表可以高效实现最近最少使用(LRU)缓存。以下是一个简单实现:

#include <iostream>
#include <unordered_map>
#include <list>
using namespace std;

// LRU 缓存类
class LRUCache {
private:
    int capacity; // 缓存容量
    list<int> keys; // 存储键的顺序
    unordered_map<int, pair<int, list<int>::iterator>> cache; // 哈希表存储键值对及其迭代器

public:
    LRUCache(int cap) : capacity(cap) {}

    int get(int key) {
        if (cache.find(key) == cache.end()) return -1; // 缓存未命中
        // 缓存命中:将键移到列表前
        keys.erase(cache[key].second);
        keys.push_front(key);
        cache[key].second = keys.begin();
        return cache[key].first;
    }

    void put(int key, int value) {
        if (cache.find(key) != cache.end()) { // 键已存在,更新值并移动到前
            keys.erase(cache[key].second);
        } else if (keys.size() == capacity) { // 缓存已满,移除最近最少使用的键
            int oldKey = keys.back();
            keys.pop_back();
            cache.erase(oldKey);
        }
        keys.push_front(key);
        cache[key] = {value, keys.begin()};
    }

    void display() {
        for (int key : keys) {
            cout << key << " ";
        }
        cout << endl;
    }
};

int main() {
    LRUCache cache(3);
    cache.put(1, 10);
    cache.put(2, 20);
    cache.put(3, 30);
    cache.display(); // 输出:3 2 1
    cache.get(1);
    cache.display(); // 输出:1 3 2
    cache.put(4, 40);
    cache.display(); // 输出:4 1 3 (2 被移除)
    return 0;
}

输出:

3 2 1 1 3 2 4 1 3

代码解释:

  • 哈希表与链表结合:哈希表提供 O(1) 的查找,链表维护键的使用顺序。
  • 缓存命中:如果键存在,将其移动到链表头部。
  • 缓存未命中:如果缓存满了,移除链表尾部的键。

改进策略:

  • 使用动态扩展的哈希表(如 Python 的 dict)。
  • 在分布式场景下采用一致性哈希,平衡节点数据。

目录

  1. 引言
  2. 哈希的本质
  3. 经典哈希函数
  4. 哈希表实现
  5. 哈希函数实现
  6. 哈希表实现
  7. 实际应用:LRU 缓存
  • 免费图片AI生成工具免费生成了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 免费图片视频在线生成30秒,将你的创意变成现实开始设计
  • X/Twitter免费视频下载器免登陆无限额度免费视频解析下载了解详情
  • 100+免费在线小游戏爽一把
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • 宇树开源 UnifoLM-VLA-0 模型实现具身智能通用操作
  • 哈希算法:冲突解决与高效查找
  • Java 图形界面编程:AWT 基础与组件体系
  • 智能体工作流导出导入实战:以 12345 热线分拨为例,零代码复用 AI 流程
  • 2025年6月GESP真题及解析:C++八级选择题与判断题
  • 基于腾讯云 HAI 与 DeepSeek 快速构建个人网页
  • 6 种 Python 脚本打包成可执行文件的主流方法
  • Python 量化金融实战:技术架构与性能优化
  • LangChain 完整指南:使用大语言模型构建应用程序
  • 哈希算法核心解析:原理、特性与实战应用
  • LLM 模型微调:PEFT 与 QLoRA 技术总结
  • Dify MCP-Server 插件将工作流发布为第三方可调用服务
  • 哈希表核心原理与 C++ 实现详解
  • Windows 下 Python 包管理工具 uv 安装与 VSCode 配置指南
  • 前端 Network 性能优化场景解析
  • C 语言实现 AI 推理优化:量化、算子融合与内存映射
  • 哈希表原理与冲突解决详解
  • Windows 版 nvm 安装配置与 Node.js 多版本管理教程
  • Stable Diffusion 3.5 云端部署与图像生成实测
  • Java Web 开发实战:数据库操作与会话管理

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online