哈希(构造哈希函数)

哈希

哈希也可以叫散列

画一个哈希表

 

 哈希冲突越多,哈希表效率越低。

闭散列开放定址法:

1.线性探测,依次往后去找下一个空位置。

2.二次探测,按2次方往后找空位置。

#pragma once
#include<vector>
#include<iostream>
#include<string>
#include<unordered_map>
using namespace std;
template<class K>
struct SetKeyOfT
{const K& operator()(const K& key){return key;}
};
//unordered_set<K>  ->HashTable<K,K>
//unordered_map<K,V>   ->HashTable<K,pair<K,V>>
enum State
{EMPTY,EXITS,DELETE,	
};
template<class T>
struct HashData//解决:该位置原来就是空还是删除后变为了空
{T _data;State _state;
};
template<class K,class T,class KeyOfT>
class HashTable//冲突了一定是连续的,但是删除会影响查找,所以应该设置状态标志。将T替换为HashData
{typedef HashData<T> HashData;
public:bool Insert(const T& d){KeyOfT koft;//负载因子=表中数据/表的大小  衡量哈希表满的程度//表越接近满,插入数据越容易冲突,冲突越多,效率越低。//哈希表并不是满了才增容,开放定址法中,一般负载因子到了0.7左右就开始增容//负载因子越小,冲突概率越低,整体效率越高,但是负载因子越小,浪费的空间越大。//所以负载因子一般去折中值if (_tables.size()==0||_num*10/_tables.size()>=7){//增容//1.开二倍大小的新表//2.遍历旧表中的数据,确定数据在新表中的映射位置//3.释放旧表vector<HashData> newtables;size_t newsize = _tables.size() == 0 ? 10 : _tables.size() * 2;newtables.resize(_tables.size() * 2);for (size_t i = 0; i < _tables.size(); ++i){if (_tables[i]._state == EXITS){size_t index = koft(_tables[i]._data % newtables.size());while (newtables[index]._state == EXITS){++index;if (index == _tables.size()){index = 0;}}newtables[index] = _tables[i];}}_tables.swap(newtables);}//KeyOfT koft;//计算d中的key在表中映射的位置size_t index = koft(d) % _tables.size();//EXITS就进行探测while (_tables[index]._state==EXITS){if (koft(_tables[index]._data) == koft(d))return false;++index;if (index == _tables.size()){index = 0;}}_tables[index]._data = d;_tables[index]._state = EXITS;_num++;return true;}HashData* Find(const K& key){KeyOfT koft;//计算d在表中映射的位置size_t index = key % _tables.size();while (_tables[index]._state != EMPTY){if (koft(_tables[index]._data) == key){if (_tables[index]._state == EXITS)return &_tables[index];else if (_tables[index]._state == DELETE)return nullptr;}++index;if (index == _tables.size()){index = 0;}}return nullptr;}bool Erase(const K& key){HashData* ret = Find(key);if (ret){ret->_state = DELETE;--_num;return true;}else{return false;}}
private:vector<HashData> _tables;size_t _num=0;//存了几个有效数据
};void TestHashTable()
{HashTable<int, int, SetKeyOfT<int>> ht;ht.Insert(4);ht.Insert(14);ht.Insert(24);ht.Insert(5);ht.Insert(15);ht.Insert(25);ht.Insert(6);ht.Insert(16);}

更优的实现方法

开散列哈希桶:

namespace OPEN_HASH
{template<class T>struct HashNode{T _data;HashNode<T>* _next;};template<class K,class T,class KeyOfT>class HashTable{public:typedef HashNode<T>* Node;bool Insert(const T& data){//1.先查找这个值在不在表中KeyOfT koft;//如果负载因子等于1,则增容,避免大量的哈希冲突if (_tables.size == _num){//增容//1.开二倍大小的新表//2.遍历旧表中的数据,确定数据在新表中的映射位置//3.释放旧表vector<Node> newtables;size_t newsize = _tables.size() == 0 ? 10 : _tables.size() * 2;newtables.resize(newsize);for (size_t i = 0; i < _tables.size(); ++i){//将旧表中的结点取下来重新计算在新表中的位置,并插入进去Node cur = _tables[i];while (cur){Node next = cur->_next;size_t index = koft(cur->_data) % newtables.size();cur->_next = newtables[index];newtables[index] = cur;cur = next;}_tables[i] = nullptr;}_tables[i].swap(newtables);}//计算数据在表中映射的位置size_t index = koft(data) % _tables.size();Node cur = _tables[index];while (cur){if (koft(cur->_data) == koft(data))return false;elsecur = cur->next;}//2.头插到挂的链表中Node newnode = new Node(data);newnode->next = _tables[index];_tables[index] = newnode;++_num;return true;}Node* Find(const K& key){KeyOfT koft;size_t index = key % _tables.size();Node cur = _tables[index];while (cur){if (koft(cur->_data) == key){return cur;}else return cur->_next;}return nullptr;}bool Erase(const K& key){KeyOfT koft;size_t index = key % _tables.size();Node prev = nullptr;Node cur = _tables[index];while (cur){if (koft(cur->_data) == key){if (prev == nullptr)//表示要删的值在一个结点_tables[index] = cur->_next;elseprev->_next = cur->_next;delete cur;return true;}else{prev = cur;cur = cur->_next;}}return false;}private:vector<Node> _tables;size_t _num=0;//记录表中存储的数据个数};
}

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

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

相关文章

告别数据泥潭:PySpark性能调优的黄金法则

阿佑今天给大家带来个一张藏宝图——使用PySpark进行性能调优的黄金法则&#xff0c;从内存管理到执行计划&#xff0c;再到并行度设置&#xff0c;每一步都是提升数据处理速度的关键&#xff01; 文章目录 Python Spark 详解1. 引言2. 背景介绍2.1 大数据处理技术演变2.2 Apac…

【MySQL】SQL基本知识点DML(2)

目录 1.DML添加数据 2.DML-修改数据 &#xff08;1&#xff09;改​编辑 &#xff08;2&#xff09;删​编辑​编辑 3.DQL-基本查询 &#xff08;1&#xff09;查询多个字段​编辑​编辑​编辑 &#xff08;2&#xff09;设置别名 &#xff08;3&#xff09;去重操作 4…

月内录用,这本期刊不到2个月完成检索

无预警毕业/晋升快刊&#xff0c;该期刊2008年被WOS收录&#xff0c;现已稳定检索16年&#xff0c;进展超顺。注意&#xff01;该期刊仅剩10篇版面&#xff01;咨询Aaron编辑老师了解该刊更多信息&#xff01; 1、期刊基本信息 【期刊简介】IF&#xff1a;0-1.0&#xff0c;J…

【SpringBoot】 什么是springboot(三)?springboot使用ajax、springboot使用reids

文章目录 SpringBoot第五章第六章1、springboot使用ajax2、springboot使用reids1、单机版**使用步骤**1-5步67-9步RedisTemplate使用RedisTemplate2、集群版开启集群项目配置1234-5第七章1、springboot文件上传使用步骤1-234-52、springboot邮件发送步骤1-23453、springboot拦截…

全球首例!猪肾移植患者死亡,人类科技与伦理或将面临挑战?

全球首例猪肾移植患者的离世&#xff0c;如同一颗重磅炸弹&#xff0c;在医学界激起千层浪花&#xff0c;让原本充满希望的“死而复生”异种器官移植技术再次被推至风口浪尖。 今年3月&#xff0c;一场与命运的较量在麻省总医院悄然落幕。全球首位接受转基因猪肾移植的患者理查…

【C++】多态(上)超详细

封装&#xff0c;继承&#xff0c;多态不只是C的三大特性&#xff0c;而是面向对象编程的三大特性。 什么是多态&#xff1a; 不同的对象做同一件事情&#xff0c;结果会出现多种形态。 1.满足多态的几个条件 1.父子类完成虚函数重写&#xff08;需要满足三同&#xff1a;函…

GD32用ST-Link出现internal command error的原因及解决方法

一、GD32 F407烧录时出现can not reset target shutting down debug session 搜寻网上资料&#xff0c;发现解决方式多种多样&#xff0c;做一个简单的总结&#xff1a; 1.工程路径包含中文名 2.需更改debug选项 3.引脚冲突 4.杜邦线太长 而先前我的工程路径包含中文名也仍…

面试集中营—Seata分布式事务

一、分布式事务 本地事务 在计算机系统中&#xff0c;更多的是通过关系型数据库来控制事务&#xff0c;这是利用数据库本身的事务特性来实现的&#xff0c; 因此叫数据库事务&#xff0c;由于应用主要靠关系数据库来控制事务&#xff0c;而数据库通常和应用在同一个服务器&am…

搭建Springboot的基础开发框架-02

本系列专题虽然是按教学的深度来定稿的&#xff0c;但在项目结构和代码组织方面是按公司系统的要求来书定的。在本章中主要介绍下基础开发框架的功能。后续所有章节的项目全是在本基础框架的基础上演进的。 工程结构介绍 SpringbootSeries&#xff1a;父工程&#xff0c;定义一…

贪吃蛇(c实现)

目录 游戏说明&#xff1a; 第一个是又是封面&#xff0c;第二个为提示信息&#xff0c;第三个是游戏运行界面 游戏效果展示&#xff1a; 游戏代码展示&#xff1a; snack.c test.c snack.h 控制台程序的准备&#xff1a; 控制台程序名字修改&#xff1a; 参考&#xff1a…

vs2019 cpp20 规范的线程头文件 <thread> 注释并探讨两个问题

&#xff08;1&#xff09;学习线程&#xff0c;与学习其它容器一样&#xff0c;要多读 STL 库的源码。很多知识就显然而然的明白了。也不用死记硬背一些结论。上面上传了一份注释了一下的 源码。主要是补充泛型推导与函数调用链。基于注释后的源码探讨几个知识点。 STL 库的多…

上位机图像处理和嵌入式模块部署(树莓派4b的软件源)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 很多文章都建议替换一下树莓派4b的软件源&#xff0c;不过我自己实际使用下来&#xff0c;官方的软件下载速度其实还可以。这里下载的时候&#xf…

mybatis-plus使用指南(1)

快速开始 首先 我们 在创建了一个基本的springboot的基础框架以后&#xff0c;在 pom文件中 引入 mybatisplus的相关依赖 <dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5…

猫头虎分享已解决Bug || 已解决ERROR: Ruby Gems安装中断 ⚠️ Bug 报告:Gem::RemoteFetcher::FetchError

猫头虎分享已解决Bug || 已解决ERROR: Ruby Gems安装中断 ⚠️ Bug 报告&#xff1a;Gem::RemoteFetcher::FetchError 博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; …

树莓派安装opencv

安装opencv 上述步骤完成后&#xff0c;输入以下代码(基于python3) sudo apt-get install python3-opencv -y不行的话&#xff0c;试试换源&#xff0c;然后 sudo apt-get update成功&#xff01; 测试opencv是否安装成功 输入 python3 然后再输入 import cv2 没有报错就…

java jdk1.8下载与安装

一、下载 1.下载jdk1.8安装包 官网下载地址&#xff1a;Java Downloads | Oracle 打开官网链接&#xff0c;下滑至Java 8模块&#xff0c;选取自己电脑适合的版本点击下载 二、安装 1.找到我们下载的安装包&#xff0c;双击运行 2.点击下一步 3.点击更改&#xff0c;修改安…

字典是如何实现的?Rehash 了解吗?

字典是 Redis 服务器中出现最为频繁的复合型数据结构。除了 hash 结构的数据会用到字典外&#xff0c;整个 Redis 数据库的所有 key 和 value 也组成了一个 全局字典&#xff0c;还有带过期时间的 key 也是一个字典。(存储在 RedisDb 数据结构中) 字典结构是什么样的呢&#xf…

Linux重定向及缓冲区理解

重定向&#xff1a; 在上一期虚拟文件系统中讲到了每个进程在打开后&#xff0c;都会默认打开3个文件&#xff0c;如下&#xff1a; stdin 标准输入&#xff08;键盘&#xff09; 文件描述符&#xff1a;0 stdout 标准输出&#xff08;显示器&#xff09;文件描述符&a…

IT项目管理-小题计算【太原理工大学】

1.合同总价问题 问承包商的利润是&#xff1f; 实际利润目标利润&#xff08;目标成本-实际成本&#xff09;*卖方分担比例 解&#xff1a;10 000&#xff08;100 000 - 90 000&#xff09;* 0.2 12 000&#xff08;元&#xff09; 实际成本有时也写作最终成本&#xff0c;问承…

XYCTF - web

目录 warm up ezMake ezhttp ezmd5 牢牢记住&#xff0c;逝者为大 ezPOP 我是一个复读机 ezSerialize 第一关 第二关 第三关 第一种方法&#xff1a; 第二种方法&#xff1a; ez?Make 方法一&#xff1a;利用反弹shell 方法二&#xff1a;通过进制编码绕过 ε…