哈希冲突的常见解决方法【附C++代码】

news2024/11/19 3:18:30

        在C++中,哈希表是一种常用的数据结构,用于实现快速的插入、删除和查找操作。

哈希表的核心在于哈希函数,它将输入的关键字转换为一个数组索引。然而,不同的关键字可能映射到相同的索引,这种情况称为哈希冲突。

有效地解决哈希冲突是确保哈希表性能的关键。

1. 开放地址法

概念:开放地址法是指当一个关键字映射的位置已经被占用时,会寻找下一个空闲的位置进行存放。查找时,若原位置没有找到,则按照同样的规则继续查找下一个可能的位置。

优点:实现简单,无需额外的数据结构。

缺点:可能会导致某些区域过于密集,影响性能;删除操作复杂

代码示例

#include <iostream>
#include <vector>

class OpenAddressingHashTable {
public:
    explicit OpenAddressingHashTable(size_t size) : table(size, -1), used(size, false) {}

    void insert(int key) {
        size_t index = key % table.size();
        while (used[index]) {
            index = (index + 1) % table.size(); // 线性探测法
        }
        table[index] = key;
        used[index] = true;
    }

    bool search(int key) {
        size_t index = key % table.size();
        while (used[index]) {
            if (table[index] == key) return true;
            index = (index + 1) % table.size();
        }
        return false;
    }

private:
    std::vector<int> table;
    std::vector<bool> used;
};

2. 链地址法(哈希桶)

概念:链地址法是在每个数组位置上挂接一个链表,所有映射到该位置的元素都存储在这个链表中。

优点:冲突少时效率高,支持动态扩容,删除操作简单。

缺点:链表过长时,查找效率降低。

代码示例(基于之前提供的哈希桶示例):

#include <iostream>
#include <list>
#include <vector>

class HashBucket {
public:
    explicit HashBucket(size_t size = 10) : buckets(size) {}

    void insert(int key, std::string value) {
        size_t index = hashFunction(key);
        buckets[index].push_back({key, value});
    }

    std::string search(int key) {
        size_t index = hashFunction(key);
        for (const auto& pair : buckets[index]) {
            if (pair.first == key) {
                return pair.second;
            }
        }
        return "Not Found";
    }

    void remove(int key) {
        size_t index = hashFunction(key);
        auto& bucket = buckets[index];
        bucket.erase(std::remove_if(bucket.begin(), bucket.end(),
                                    [key](const auto& p){ return p.first == key; }),
                     bucket.end());
    }

private:
    std::size_t hashFunction(int key) const {
        return key % buckets.size(); // 简单的取模哈希函数
    }

    std::vector<std::list<std::pair<int, std::string>>> buckets;
};

int main() {
    HashBucket hashTable;

    hashTable.insert(10, "Apple");
    hashTable.insert(25, "Banana");
    hashTable.insert(20, "Cherry");

    std::cout << "Search 10: " << hashTable.search(10) << std::endl; // 应输出 Apple
    std::cout << "Search 30: " << hashTable.search(30) << std::endl; // 应输出 Not Found

    hashTable.remove(20);
    std::cout << "Search 20 after removal: " << hashTable.search(20) << std::endl; // 应输出 Not Found

    return 0;
}

3. 再哈希法

概念:当发生冲突时,使用第二个哈希函数计算另一个位置,如果仍冲突,则继续使用第三个或更多哈希函数,直到找到空位。

优点:可以减少聚集现象。

缺点:需要设计多个哈希函数,增加了实现复杂度。

代码示例(简略示例):

class RehashHashTable {
public:
    void insert(int key) {
        size_t index = primaryHash(key);
        if (isOccupied(index)) {
            index = secondaryHash(key); // 假设这是第二个哈希函数
            // 可能需要更多的检查和重哈希直到找到空位
        }
        // 实际插入逻辑省略
    }

private:
    size_t primaryHash(int key) { /* 主哈希函数实现 */ }
    size_t secondaryHash(int key) { /* 辅助哈希函数实现 */ }
    bool isOccupied(size_t index) { /* 检查位置是否已被占用 */ }
};

4. 建立公共溢出区(使用率低)

概念:当主表满时,额外分配一块区域作为溢出区,所有冲突的元素都放入这个区域,并以某种顺序(如链表)链接起来。

优点:实现简单。

缺点:查找效率较低,因为可能需要遍历整个溢出区。

        解决哈希冲突的策略各有优劣,选择哪种方法取决于具体的应用场景和性能要求。开放地址法适合内存有限且数据量不大的情况;链地址法则更适合数据量大且需要频繁插入删除的场景;再哈希法和建立公共溢出区则是针对特定需求的解决方案,可能在某些特殊场景下更为合适。

        在实际应用中,还需要考虑哈希函数的设计、哈希表的动态扩容机制等因素,以进一步优化性能。C++标准库中的std::unordered_mapstd::unordered_set就是使用了类似链地址法的实现,结合了动态扩容机制,提供了高效的哈希表操作接口。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1710345.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【MIT 6.5840(6.824)学习笔记】GFS

1 分布式存储系统难点 在设计大型分布式系统或存储系统时&#xff0c;初衷通常是为了获得显著的性能提升&#xff0c;通过数百台计算机的资源来并行完成大量工作。因此&#xff0c;性能问题成为最初的关注点。一个自然的想法是将数据分片&#xff08;Sharding&#xff09;&…

GPT-4 与 GPT-4 Turbo有什么区别?

在不断发展的人工智能和自然语言处理领域&#xff0c;OpenAI 的 GPT 系列一直走在最前沿&#xff0c;彻底改变了机器理解和生成类人文本的方式。每一次迭代&#xff0c;进步都会突破可能性的界限。 最新的条目 GPT-4 和 GPT-4 Turbo 引起了人工智能社区内外的极大兴趣和争论。…

保留字与标识符

目录 保留字 标识符 自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 保留字 保留字是Python语言中一些已经被赋予特定意义的单词。开发程序时&#xff0c;不可以把这些保留字作为变量、函数、类、…

河道流量监测解决方案 河道水位监测 水质在线监测-计讯物联科技

在城市河道与入海口间的通道施工项目中&#xff0c;拦水坝不仅承担着调节水流、保护生态平衡的使命&#xff0c;也是确保施工区域安全的关键屏障。当前&#xff0c;项目团队面临着严峻的挑战&#xff1a;水位的异常上升和流量的急剧变化&#xff0c;这些都可能对拦水坝的稳定性…

公司预防文件泄密的常见手段 | 文件防泄密软件推荐排行榜

在当今信息化社会&#xff0c;企业面临着越来越多的文件泄密风险。为了保护企业的核心信息和资产&#xff0c;公司需要采取一系列手段来预防文件泄密。本文将介绍公司预防文件泄密的常见手段&#xff0c;并推荐五款优秀的防泄密软件&#xff0c;帮助企业构建更为严密的数据安全…

Mongodb 可视化工具Robot 3t安装【windows环境下】

下载应用 打开连接点我 选择windows版本并点击下载 下载完毕&#xff0c;双击并傻瓜安装 连接数据库 点击图标&#xff0c; 点击create创建连接 填写host和port 如果有用户名密码的&#xff0c;在authentication里填写 5. save 并连接即可使用&#xff01;

Python自动化办公Excel数据处理实战指南

目录 一、引言 二、需求分析 三、技术选型 四、实战操作 数据读取 数据清洗 数据分析 数据输出 五、学习资源推荐&#xff1a; 六、结语 一、引言 在现代办公环境中&#xff0c;Excel数据处理是一项不可或缺的技能。然而&#xff0c;当数据量庞大、处理流程复杂时&a…

页面加载不出来,报错[@umijs/runtime] load component failed

问题描述 页面加载不出来数据&#xff0c;一直在旋转&#xff0c;控制台输出内容如下&#xff1a; 原因分析&#xff1a; 之前页面是没有问题的&#xff0c;在写当前页面突然出现页面加载不出来&#xff0c;控制台报错&#xff0c;主要是页面引入了这行代码报错 import { …

教育小程序的性能优化:从前端到后端的综合提升策略

随着教育小程序的普及&#xff0c;其性能直接影响用户体验和教学效果。本文将从前端到后端&#xff0c;详细探讨教育小程序的性能优化策略&#xff0c;帮助开发者打造高效、流畅的教育应用。 一、前端性能优化策略 代码优化 减少HTTP请求&#xff1a;合并CSS、JavaScript文件…

安装CUDA Toolkit解决异常:OSError: CUDA_HOME environment variable is not set.

安装CUDA Toolkit 安装CUDA Toolkit异常信息分析下载CUDA执行安装配置环境变量验证 安装CUDA Toolkit 异常信息 在执行pip install flash_attn&#xff0c;安装一个推理加速库的时候&#xff0c;遇到如下异常&#xff1a; Looking in indexes: https://mirrors.aliyun.com/p…

RocketMQ学习(1) 快速入门

mq的一些前置知识和概念知识可以看这篇文章——SpringCloud入门(3) RabbitMQ&#xff0c;比如常见mq的对比等等&#xff0c;这篇文章不再赘述。 目录 RocketMQ概念、安装与配置docker配置 RocketMQ快速入门**同步消息消费模式 **异步消息*单向消息**延迟消息*顺序消息批量消息事…

探索Python函数参数的奥秘

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、揭开函数参数的神秘面纱 1. 位置参数&#xff1a;按序传值的基石 2. 关键字参数&#…

修改Windows系统hosts文件,解决GitHub国内访问速度慢甚至无法访问的问题

对国内大多数用户&#xff0c;GitHub的访问速度非常慢&#xff0c;甚至是打不开&#xff0c;无法访问。究其原因&#xff0c;多数是GitHub的CDN域名解析&#xff08;DNS&#xff09;遭到了污染或拦截。本文以Windows 10系统为例&#xff0c;通过修改本地hosts文件&#xff0c;解…

基于jeecgboot-vue3的Flowable流程-我的任务(一)

因为这个项目license问题无法开源&#xff0c;更多技术支持与服务请加入我的知识星球。 1、首先可以用现成生成代码的前端来做这个&#xff0c;只要做一些调整就可以了&#xff0c;这样利用现有的一些模板可以快速构建我的任务&#xff0c;否则vue2与vue3相差太大&#xff0c;移…

Linux虚拟主机中如何创建文件和文件夹

我想创建一个新的文件夹&#xff0c;由于我使用的Hostease的Linux虚拟主机产品默认带普通用户权限的cPanel面板&#xff0c;但是不知道如何在cPanel上操作创建文件&#xff0c;因为也是对于Hostease主机产品不是很了解&#xff0c;因此联系Hostease的咨询了Hostease技术支持&am…

C++基础练手项目之贪吃蛇

同理上一篇写的 http://t.csdnimg.cn/TPFwu 就是画一个地图,用二维数组,来记录X和Y轴,就可以定义到这个地图的任意位置. 目录 一.步骤解析 二.代码 三.扩展 一.步骤解析 开始函数,变量值重置为默认状态,蛇的头,尾生成位置都可以,随便更改,我这里先默认写死了, 循环等待输入…

移除重复节点

题目链接 移除重复节点 题目描述 注意点 链表未排序链表长度在[0, 20000]范围内链表元素在[0, 20000]范围内 解答思路 使用Set存储访问过的链表中出现的节点值&#xff0c;当遍历到链表的某个节点在Set中出现过&#xff0c;则需要将该节点的前一个节点next指针指向该节点的…

护眼灯到底有用吗?引发护眼台灯危害的四大原因曝光!

护眼灯到底有用吗&#xff1f;近几年随着各大科技感满满的设备诞生&#xff0c;近视率也伴随着不断提高&#xff0c;现如今是已经攀升到了惊人的53.6%&#xff0c;这一数据也清晰的警惕着每一位家长&#xff0c;此刻护眼灯以独特的护眼效果脱颖而出&#xff0c;同时也在书房中占…

Linux - crond任务调度、at定时任务

1 crontab 进行-定时任务的设置 1&#xff09;概述&#xff1a; 任务调度&#xff1a;是指系统在某个时间执行的特定的命令或程序。 任务调度分类&#xff1a; 系统工作&#xff1a;有些重要的工作必须周而复始地执行。如病毒扫描等个别用户工作&#xff1a;个别用户可能希…

UE5 Cesium2 最新使用地理配准子关卡构造全球场景

参考官方最新教程&#xff1a;Building Global Scenes with Georeferenced Sublevels – Cesium 创建持久关卡&#xff08;主关卡&#xff09; 这里一般包含DynamicPawn、CesiumSunSky 和 Cesium World Terrain 全球场景通用的对象。子关卡的创立&#xff0c;官方教程分为了两…