首页 > 编程语言 >哈希算法篇——散落的秘密与精准的归宿,混沌中的秩序之美(上)

哈希算法篇——散落的秘密与精准的归宿,混沌中的秩序之美(上)

时间:2025-01-02 19:56:32浏览次数:3  
标签:哈希 int cache 之美 算法 key 精准 函数

文章目录


在这里插入图片描述

引言:混沌中的秩序之美

在信息科学的星空下,有一种算法宛如一位洞悉混沌的智者,能够以其独特的规则,在无限的可能性中找到秩序。这便是哈希算法(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,这些算法旨在提供高安全性特性,广泛用于密码存储、数字签名和区块链技术。它们的特点是:

  • 抗碰撞性:难以找到两个不同输入对应同一输出。
  • 雪崩效应:输入的微小变化会显著改变输出。
  1. 非加密哈希算法:
    如 MurmurHash 和 CityHash,它们不强调安全性,但在性能和冲突率上表现优异,常用于数据库和分布式系统。

第三章:哈希表的奇迹——从无序到有序的转变

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

哈希表的操作:

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

哈希表的优点:

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

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

  • 链地址法:将冲突的键值对存储为链表。
  • 开放地址法:通过线性探测或二次探测寻找空闲位置。

哈希表在现代编程语言中的实现十分广泛,如 C++ 的 std::unordered_map 和 Python 的 dict。

3.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 值累加起来。
  • 然后通过取模操作,将累加结果映射到一个固定范围(哈希表的大小)。
  • 尽管简单,但这种方法容易引发哈希冲突,因为不同的输入可能映射到相同的哈希值。

3.2 基本的哈希表实现

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

#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)中的链表中,解决哈希冲突。
  • 插入操作:通过哈希函数计算键的索引,将键插入到对应桶中。
  • 查找操作:定位到桶后,遍历桶内的链表查找目标键。

3.3 哈希算法的实际应用

哈希表结合链表可以高效实现最近最少使用(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)。
  • 在分布式场景下采用一致性哈希,平衡节点数据。

小结

本篇关于哈希算法的介绍就暂告段落啦,希望能对大家的学习产生帮助,欢迎各位佬前来支持斧正!!!

在这里插入图片描述

标签:哈希,int,cache,之美,算法,key,精准,函数
From: https://blog.csdn.net/2303_81060385/article/details/144844151

相关文章

  • 《数据质量评估方法大揭秘:精准衡量数据价值的关键》
    在当今数字化时代,数据已成为企业和组织决策的重要依据,而数据质量的评估则是确保数据价值的关键环节。以下是一些常见的数据质量评估方法:准确性评估与权威数据比对:将自身数据与同领域、同区域、同时期的权威数据进行对比,如环保部门公开发布的监测数据等。若差异显著,需分析......
  • Linux 定时任务:轻松创建与精准执行
    Linux定时任务:轻松创建与精准执行在Linux系统的运维与自动化管理领域,定时任务扮演着举足轻重的角色。它能够让系统在预设的时间点或周期性时段,自动执行特定的脚本、命令,极大地减轻了管理员的工作负担,提升工作效率。接下来,就让我们深入探究Linux定时任务的创建与执行细......
  • Luogu P9646 SNCPC2019 Paper-cutting 题解 [ 紫 ] [ manacher ] [ 贪心 ] [ 哈希 ] [
    Paper-cutting:思维很好,但代码很构式的manacher题。蒟蒻2025年切的第一道题,是个紫,并且基本独立想出的,特此纪念。判断能否折叠我们先考虑一部分能折叠需要满足什么条件。显然,这一部分需要是一个长度为偶数的回文串。那么横向和纵向会不会影响呢?答案是不会,因为横向折了之后,折......
  • Spring Boot 使用 Redis 实现布隆过滤器,精准过滤 “无效” 请求
    SpringBoot使用Redis实现布隆过滤器,精准过滤“无效”请求在当今高并发的互联网应用场景下,如何高效地对海量数据进行过滤,避免无效请求对系统资源造成浪费,是每一个开发者都需要面对的问题。布隆过滤器(BloomFilter)作为一种空间效率极高的概率型数据结构,为我们提供了出......
  • AI技术在药品说明书的应用,开启精准用药的新时代
    药品说明书,作为指导患者安全用药的重要指南,长期以来却因其专业性强、信息量大、更新滞后等问题,难以被普通大众充分理解和利用。如今,人工智能(AI)的崛起为药品说明书的革新带来了曙光。AI正以其强大的数据处理和学习能力,深度赋能药品说明书的各个环节,从生成、更新到解读、应用,全......
  • 中南大学(CSU)世界杯球赛(10分)—— 哈希表的使用
        孩子们,我回来了。最近OJ的作业比较多,一不小心写昏过去了。在写世界杯球赛这一题时经常因为程序较复杂,运行时间太久而导致时间超限。为此,我痛定思痛,在查阅资料后找到了一种高效、灵活的数据结构——哈希表。现在,我将以这一道题为例来分享哈希表的简单使用。(提示:本......
  • Leecode热题100——1.哈希
    1.两数之和给定一个整数数组nums和一个整数目标值target,请你在该数组中找出和为目标值target的那两个整数,并返回它们的数组下标。你可以假设每种输入只会对应一个答案,并且你不能使用两次相同的元素。你可以按任意顺序返回答案。示例1:输入:nums=[2,7,11,15],target......
  • python中的可不可变,可不可哈希,可不可修改
    在Python中,可不可变性、可不可哈希性、以及是否支持修改是理解数据类型行为的关键。以下是对这些特性的详细分析,包括定义、例子和它们之间的联系。1.可变性vs不可变性定义可变性:可变类型的数据可以直接修改,而不会改变其引用(内存地址)。不可变性:不可变类型的数据在创建后......
  • 常见加密方式:对称加密,非对称加密和哈希算法
    前言长度位数,字符规律数据加密是一种保护数据安全的技术,通过将数据明文转换为不易被未授权的人理解的形式密文,防止数据泄露、串改和滥用。对称加密加密和解密使用同一密钥,加解密速度快,适合加密大量数据。但密钥需要安全地存储和传输,否则容易窃取,破坏数据地保密性。DES明......
  • 六轴MEMS寻北仪:精准寻北,微型巨献
    在定向技术领域的持续探索中,高精度与小型化的完美结合一直是行业发展的核心驱所在。为此,一款名为ER-MNS-06的六轴MEMS寻北仪应运而生,以其卓越的性能和微型化的设计,在众多应用中脱颖而出。***全球最小六轴MEMS寻北仪***这款寻北仪集成了三轴MEMS陀螺仪和三轴加速度计,实现了对......