哈希(构造哈希函数)

哈希

哈希也可以叫散列

画一个哈希表

 

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

闭散列开放定址法:

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.mzph.cn/diannao/10993.shtml

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

相关文章

Linux重定向及缓冲区理解

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

每日OJ题_贪心算法四⑤_力扣354. 俄罗斯套娃信封问题

目录 力扣354. 俄罗斯套娃信封问题 解析代码1_动态规划&#xff08;超时&#xff09; 解析代码2_重写排序贪心二分 力扣354. 俄罗斯套娃信封问题 354. 俄罗斯套娃信封问题 难度 困难 给你一个二维整数数组 envelopes &#xff0c;其中 envelopes[i] [wi, hi] &#xff0…

25计算机考研院校数据分析 | 中南大学

中南大学&#xff08;Central South University&#xff09;&#xff0c;位于湖南省长沙市&#xff0c;是中华人民共和国教育部直属的全国重点大学 &#xff0c;中央直管副部级建制&#xff0c;位列国家“双一流”、“985工程”、“211工程”&#xff0c;入选国家“2011计划”牵…

陪玩系统APP小程序H5音视频社交系统陪玩系统源码,陪玩app源码,陪玩源码搭建陪玩社交系统开发(现成,可定制)线下陪玩系统项目开发搭建

线下陪玩系统项目的设计 在需求分析完成后&#xff0c;接下来进行系统设计。系统设计主要包括以下几个部分&#xff1a; 1. 数据库设计&#xff1a;根据需求分析的结果&#xff0c;设计数据库结构&#xff0c;包括用户信息表、服务信息表、订单信息表等。 2. 界面设计&#…

阮怀俊参与五龙乡黄沙村村企联办“强村公司”

为走好海岛县高质量发展共同富裕特色之路&#xff0c;探索村级集体经济发展新路径、扶持新模式、运行新机制&#xff0c;嵊泗县五龙乡黄沙村股份经济合作社与杭州山舍乡建乡村产业发展有限责任公司联办成“强村公司”。 创始人阮怀俊表示&#xff0c;双方就融合乡域发展和文旅产…

MFC桌面应用中窗口的客户区与非客户区的

在MFC&#xff08;Microsoft Foundation Class&#xff09;中&#xff0c;窗口被分为客户区和非客户区。理解这两个概念对于设计和开发Windows应用程序至关重要。 客户区&#xff08;Client Area&#xff09;&#xff1a; 客户区是窗口中用于显示应用程序内容的区域。它是窗口…

PXE高效批量装机

一、PXE的概述 PXE是由Inter 公司开发的网络引导技术&#xff0c;工作在Client / Server 模式。允许客户机通过网络从远程服务器下载引导镜像&#xff0c;并加载安装文件或者整个操作系统。 1.1PXE优点 规模化&#xff1a;同时装配多台服务器 自动化&#xff1a;安装系统&am…

力扣10.正则表达式匹配

前言&#xff1a; 由于今天面试前端&#xff0c;面试官问对正则表达式的匹配理解吗&#xff1f; 当时脑袋发热&#xff0c;我说就是对字符串的替换。。。。 太抽象了&#xff0c;于是我面试结束后马上打开力扣&#xff0c;解了正则表达式的匹配算法题(四种语言)&#xff1b; 下…

03c++重载运算符

1、深入理解new和delete原理 #include<iostream> using namespace std;/* new 和 delete 1、malloc和new的区别 new 内存开辟构造函数 2、free和 delete的区别 delete 内存回收析构函数 开辟失败malloc返nullptr ,new抛出bad_alloc异常new->operator new delete -&…

回归预测 | Matlab实现GA-LSSVM遗传算法优化最小二乘支持向量机多输入单输出回归预测

回归预测 | Matlab实现GA-LSSVM遗传算法优化最小二乘支持向量机多输入单输出回归预测 目录 回归预测 | Matlab实现GA-LSSVM遗传算法优化最小二乘支持向量机多输入单输出回归预测预测效果基本介绍模型描述程序设计参考资料 预测效果 基本介绍 Matlab实现GA-LSSVM遗传算法优化最小…

Linux进程控制——Linux进程终止

前言&#xff1a;前面了解完前面的Linux进程基础概念后&#xff0c;我们算是解决了Linux进程中的一大麻烦&#xff0c;现在我们准备更深入的了解Linux进程——Linux进程控制&#xff01; 我们主要介绍的Linux进程控制内容包括&#xff1a;进程终止&#xff0c;进程等待与替换&a…

车载测试:为什么你投十份简历,只有一两家公司约你?

最根本的原因&#xff0c;就是一方在汲汲渴求&#xff0c;而恰恰另一方呈现出的关键点让其怦然心动。求者心中有所想&#xff0c;而应者恰恰展现了求者所想的那一面。这就是个中奥妙。 程序员在找工作时&#xff0c;在一开始有三件事情会对能否获得面试机会至关重要&#xff1…

计算机毕业设计springboot+vue高校教师职称评审评定系统605z3

技术栈 前端&#xff1a;vue.jsElementUI 开发工具&#xff1a;IDEA 或者eclipse都支持 编程语言: java 框架&#xff1a; ssm/springboot 数据库: mysql 版本不限 数据库工具&#xff1a;Navicat/SQLyog都可以 详细技术&#xff1a;javaspringbootvueMYSQLMAVEN 本系统采用in…

MySQL相关文件的介绍

其中的pid-file/var/run/mysqld/mysqld.pid是用来定义MySQL的进程ID的信息的&#xff0c; 这个ID是操作系统分配给MySQL服务进程的唯一标识&#xff0c;使得系统管理员可以轻松识别和管理该进程。 其中的log-error/var/log/mysqld.log是MySQL的错误日志文件&#xff0c;如果有…

Matlab-粒子群优化算法实现

文章目录 一、粒子群优化算法二、相关概念和流程图三、例题实现结果 一、粒子群优化算法 粒子群优化算法起源于鸟类觅食的经验&#xff0c;也就是一群鸟在一个大空间内随机寻找食物&#xff0c;目标是找到食物最多的地方。以下是几个条件: (1) 所有的鸟都会共享自己的位置以及…

2024中国(重庆)无人机展览会8月在重庆举办

2024中国(重庆)无人机展览会8月在重庆举办 邀请函 主办单位&#xff1a; 中国航空学会 重庆市南岸区人民政府 招商执行单位&#xff1a; 重庆港华展览有限公司 报名&#xff1a;【交易会I 59交易会2351交易会9466】 展会背景&#xff1a; 为更好的培养航空航天产业和无人…

【linux学习】多线程(1)

文章目录 线程的概念线程与进程 线程的用法线程的创建多线程 线程的等待线程锁死锁 线程的概念 在Linux中&#xff0c;线程&#xff08;Thread&#xff09;是程序执行流的最小单位&#xff0c;是进程中的一个实体&#xff0c;负责在程序中执行代码。线程本身不拥有系统资源&…

支持视频切片的开源物联网平台

软件介绍 MzMedia开源视频联动物联网平台是一个简单易用的系统,该平台支持主流短视频平台&#xff08;如抖音、快手、视频号&#xff09;的推流直播功能&#xff0c;同时提供视频切片等功能。系统后端采用Spring Boot&#xff0c;前端采用Vue3和Element Plus&#xff0c;消息服…

计算机毕业设计python校园二手交易系统aqj3i-

什么叫三层架构呢&#xff1f;指的是表示层、组件层、数据访问层。组件层是双层架构没有的&#xff0c;它的加入&#xff0c;把复杂的问题分解得更简单、明了&#xff0c;通过组件层&#xff0c;实现控制数据访问层&#xff0c;这样达到功能模块易于管理、易于访问等目的&#…

<MySQL> 数据库基础

目录 一、数据库概念 &#xff08;一&#xff09;什么是数据库 &#xff08;二&#xff09;数据库存储介质 &#xff08;三&#xff09;常见数据库 二、数据库基本操作 &#xff08;一&#xff09;连接数据库 &#xff08;二&#xff09;使用数据库 &#xff08;三&…