【C++】哈希二

上篇博客我们写了解决哈希冲突的两种办法,不过我们写的都是针对整形的,而在实际情况下,要存入哈希表中的数据可以是string自定义类型等等。那么我们就应该想一种办法去解决这里的问题。

比如说string,我们想到如何让string也转为整形,本质上就是利用一个哈希函数将字符串转化为哈希值,也就是整形。比如我们可以让字符串中每一个字符的ACSCII值相加,但这样容易重复,我们可以让它们乘以一个不同的数在进行相加,这样重复率会低一些。于是就有人研究这种问题,怎么才能让重复率尽可能的低呢?

于是有人提出一种BKDRhash,下面有一个简单的解释,

于是我们就可以来实现一下,我们这里实现成仿函数的形式,为了方便后面给哈希表传参数

其实类似的哈希函数还有很多,我们这里就以这个为例子。其实库中也是这么实现的

说完了字符串,再举一个例子,比如说日期类,其实我们也让年月日分别乘一个数就行,或者有其他的合适的方式都可以

我们知道,unordered_map和unordered_set就是用哈希表封装出来的

我们如果用string当key值的话,是直接可以编译过的,而日期类却不行,这是因为string经常做key,所以在库中做了特化处理,就是模板进阶部分说的特化

我们可以看到哈希函数是有缺省值的,我们用一些它支持的类型是不用传的,并且对于string来说是一种类模板的特化,就是只要key是string,就调用特化版本的,大概像这样

对于int就会调用第一个,对于string就会调用特化版的第二个

那么接下来我们就接着上篇博客,加上模板等一系列的操作,并且哈希桶由于是去上开空间,所以我们还需要写一个析构函数,否则会造成内存泄漏。因为我们后边还要用这个封装出unordered_map和unordered_set

我下边只是对于哈希桶版本进行了一些修改

template<class T>
struct hashfun {
	size_t operator()(const T& key) {
		return (size_t)key;
	}
};
template<>
struct hashfun<string> {
	size_t operator()(const string& str) {
		size_t hashret = 0;
		for (auto& e : str) {
			hashret = hashret * 131 + e;
		}
		return hashret;
	}
};
namespace hash_bucket {
	template<class K,class V>
	struct HashNode {
		HashNode(const pair<K,V>&vall)
			:val(vall)
			,_next(nullptr){}

		pair<K,V> val;
		HashNode<K,V>* _next = nullptr;
	};
	template<class K,class V,class hashfunc=hashfun<K>>
	class HashTable {
		typedef HashNode<K, V> Node;
	public:
		HashTable(size_t n=10) {
			_hashvec.resize(n, nullptr);
		}
		~HashTable() {
			for (size_t i = 0; i < _hashvec.size(); i++) {
				Node* cur = _hashvec[i];
				Node* next = nullptr;
				while (cur) {
					next = cur->_next;
					delete cur;
					cur = next;
				}
			}
		}
		Node* find(const K&key) {
			size_t hashi = hashfunc()(key) % _hashvec.size();
			Node* cur = _hashvec[hashi];
			while (cur) {
				if (cur->val.first == key)return cur;
				cur = cur->_next;
			}
			return nullptr;
		}
		bool insert(const pair<K,V>&_kv) {
			if (find(_kv.first))return false;
			if (_n == _hashvec.size()) {
				//扩容
				HashTable newtable(_hashvec.size() * 2);
				for (size_t i = 0; i < _hashvec.size(); i++) {
					Node* cur = _hashvec[i];
					Node* next = nullptr;
					while (cur) {
						next = cur->_next;
						size_t hashi = hashfunc()(cur->val.first) % newtable._hashvec.size();
						cur->_next = newtable._hashvec[hashi];
						newtable._hashvec[hashi] = cur;
						cur = next;
					}
					_hashvec[i] = nullptr;
				}
				_hashvec.swap(newtable._hashvec);
			}
			size_t hashi = hashfunc()(_kv.first) % _hashvec.size();
			Node* newnode = new Node(_kv);
			newnode->_next = _hashvec[hashi];
			_hashvec[hashi] = newnode;
			++_n;
			return true;
		}
		bool erase(const K&key) {
			size_t hashi = hashfunc()(key) % _hashvec.size();
			Node* prev = nullptr;
			Node* cur = _hashvec[hashi];
			while (cur&&cur->val != key) {
				prev = cur;
				cur = cur->_next;
			}
			if (cur == nullptr)return false;
			if (prev == nullptr) {
				_hashvec[hashi] = cur->_next;
			}
			else {
				prev->_next = cur->_next;
			}
			delete cur;
			return true;
		}
	private:
		size_t _n = 0;
		vector<Node*> _hashvec;
	};
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

代码随想录算法练习Day11:链表相交

题目&#xff1a;给你两个单链表的头节点 headA 和 headB &#xff0c;请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点&#xff0c;返回 null 。 题目链接&#xff1a;160.链表相交 题目思路&#xff1a;定义两个指针&#xff0c;分别遍历两链表&#xff0c;如…

后端获取请求体Body,将请求体进行解密放回Request请求,并能通过@RequestBody获取

目前系统发送的post和put请求都是没有加密数据。客户需要将请求体加密。而系统已经基本开发完成&#xff0c;不可能一个一个去修改发送的请求。就需要在发送请求时候在拦截器中将body进行加密。并且在后端进行请求过滤解密&#xff0c;并且能通过RequestBody继续获取对象。 1.…

RuoYi-Cloud部署实战(手动部署)

RuoYi-Cloud部署实战 语雀 1. 若依源码和架构 RuoYi-Cloud: &#x1f389; 基于Spring Boot、Spring Cloud & Alibaba的分布式微服务架构权限管理系统&#xff0c;同时提供了 Vue3 的版本 若依项目结构 带端口号的是需要启动的服务 com.ruoyi ├── ruoyi-ui …

各大厂都推出鸿蒙APP了,你就一定要学习一下鸿蒙APP测试了!

2023年8月&#xff0c;华为推出鸿蒙4.0&#xff0c;由于其广泛的用户基础和品牌传播力&#xff0c;在短短几个月的时间&#xff0c;使用鸿蒙4.0系统的设备就达到千万级别&#xff0c;并且在9月份发售Mate 6之后&#xff0c;还在装机量的增长更加迅猛。 基于此&#xff0c;11月…

德立电子授权世强先进代理分销,加速车规级磁性元器件产品拓展

为提供先进、可靠的磁性元件产品&#xff0c;世强先进&#xff08;深圳&#xff09;科技有限公司与惠州市德立电子有限公司&#xff08;下称“德立电子”&#xff0c;英文名&#xff1a;DDY&#xff09; 签署授权代理合作协议&#xff0c;旨在为汽车电子、工业、消费、通信、医…

Java GUI制作双人对打游戏(上)

文章目录 前言什么是Java GUI一、打开IDEA 新建一个Maven项目(后续可以打包、引入相关依赖也很容易)二、引入依赖三.绘制UI界面四.绘制JPanel面板总结 前言 什么是Java GUI Java UI&#xff0c;即Java用户界面&#xff0c;是指使用Java编程语言创建的图形用户界面&#xff08…

实现分布式锁

实现分布式锁的两个核心&#xff1a; 一、获取锁 1、获取锁线程互斥性 为了实现只有一个线程能继续执行业务代码&#xff0c;必须保证获取锁具有互斥性&#xff0c;即只有一个线程能获取到锁。 Redis中操作数据是单线程的&#xff0c;可以使用Redis提供的set nx ex命令获取锁。…

鸿蒙原生应用元服务-访问控制(权限)开发等级和类型

一、权限等级说明 根据接口所涉数据的敏感程度或所涉能力的安全威胁影响&#xff0c;ATM模块定义了不同开放范围的权限等级来保护用户隐私。 应用APL等级说明 元能力权限等级APL&#xff08;Ability Privilege Level&#xff09;指的是应用的权限申请优先级的定义&#xff0c;…

Ubuntu 22.04 安装 zabbix

Ubuntu 22.04 安装 zabbix 1&#xff0c;Install Zabbix repository2&#xff0c;安装Zabbix server&#xff0c;Web前端&#xff0c;agent3&#xff0c;安装mysql数据库3.1 创建初始数据库3.2 导入初始架构和数据&#xff0c;系统将提示您输入新创建的密码。3.3 在导入数据库架…

课题学习(二十一)----姿态更新的四元数算法推导

声明&#xff1a;本人水平有限&#xff0c;博客可能存在部分错误的地方&#xff0c;请广大读者谅解并向本人反馈错误。    最近需要使用AEKF对姿态进行结算&#xff0c;所以又对四元数进了深入的学习&#xff0c;本篇博客仅对四元数进行推导&#xff0c;后续会对基于四元数的…

kafka学习笔记03

SpringBoot2.X项目搭建整合Kafka客户端依赖配置 用自己对应的jdk版本。 先加上我们的web依赖。 添加kafka依赖: SpringBoot2.x整合Kafka客户端adminApi单元测试 设置端口号。 新建一个kafka测试类&#xff1a; 创建一个初始化的Kafka服务。 设置kafka的名称。 测试创建kafka。…

Gitee和Git学习笔记

Gitee和Git指令 Gitee提交代码方法1 先将仓库clone到本地&#xff0c;修改后再push到 Gitee 的仓库方法2 本地初始化一个仓库&#xff0c;设置远程仓库地址后再做push 切换分支下载代码通过git clone克隆仓库通过下载 ZIP 的方式下载代码 Git提交指令 解决本地库同时关联GitHub…

数据库SQL语言实战(三)

删除操作 本篇文章重点在于SQL中的各种删除操作 题目一 删除表中的学号不全是数字的那些错误数据&#xff0c;学号应该是数字组成&#xff0c;不能够包含字母空格等非数字字符。方法之一&#xff1a;用substr函数&#xff0c;例如Substr(sid,1,1)返回学号的第一位&#xff0…

数据库信息/密码加盐加密 —— Java代码手写+集成两种方式,手把手教学!保证能用!

&#x1f9f8;欢迎来到dream_ready的博客&#xff0c;&#x1f4dc;相信您对博主首页也很感兴趣o (ˉ▽ˉ&#xff1b;) 博主首页&#xff0c;更多redis、java等优质好文以及各种保姆级教程等您挖掘&#xff01; 目录 需求分析 常用案例举例 加盐加密逻辑如何对比原数据&…

分布式光纤测温解决方案

安科瑞电气股份有限公司 祁洁 15000363176 一、方案介绍 分布式光纤测温&#xff08;DTS&#xff09;集光电信号检测、计算机技术等为一体&#xff0c;具有实时监测、测温精度高、测量距离长、可精确定位、采用光纤作为传感器和传输介质&#xff0c;具有抗电磁干扰、本征防…

GVRP协议与动态、静态vlan

一、GVRP协议使用场景 1、当实际组网复杂到网络管理员无法短时间内了解网络的拓扑结构&#xff0c;或者是整个网络的VLAN太多时&#xff0c;工作量会非常大&#xff0c;而且非常容易配置错误。在这种情况下&#xff0c;用户可以通过GVRP的VLAN自动注册功能完成VLAN的配置。 2、…

【Vue3】setup语法糖的使用

文章目录 setup简介使用vite-plugin-vue-setup-extend插件 指定组件名字 setup简介 <script setup> 是在单文件组件 (SFC) 中使用组合式 API 的编译时语法糖 相比较普通的<script> ,它有以下优势&#xff1a; 更少的样板内容&#xff0c;更简洁的代码。能够使用纯…

【教程】如何使用ArcPy快速批量的处理数据

前面介绍了如何构建自己的ArcGIS工具箱&#xff0c;能够极大地减轻繁琐重复的工作&#xff0c;可查看&#xff1a; 【教程】如何自制一个ArcGIS工具箱&#xff08;ArcPy和模型构建器的使用&#xff09; 除了制作工具箱来实现自动处理重复性的工作&#xff0c;还可以使用ArcPy…

解决Error (169281)、Error (169282)报错问题,QuartusII设置Virtual Pin虚拟管脚的详细操作方法

解决Error(169281)、Error(169282)报错问题,QuartusII设置Virtual Pin虚拟管脚的详细操作方法 1,QuartusII报错信息2,解决办法3,重新编译,成功参考文献: 1,Quartus如何设置虚拟管脚Virtual Pin(具体设置方法) 1,QuartusII报错信息 报错原因:    为了验证FPGA工…

vr兽医设备操作模拟仿真教学平台提升教学效果

在兽医教育的传统领域中&#xff0c;动物诊疗一直是一项不可或缺的实践环节。然而&#xff0c;传统的解剖教学方式受限于动物数量、种类以及安全隐患&#xff0c;无法充分满足学生的学习需求。随着VR虚拟仿真技术的不断精进&#xff0c;VR动物诊疗仿真实训系统为兽医教育带来了…