哈希--直接定值法和除留取余法

数据结构与算法C++实现(10)之哈希表 一、概念 散列技术是在记录的存储位置和他的关键字之间建立一个确定的对应关系f,是的每个关键字key对应一个存储位置f(key)。查找时,根据这个对应的关系找到给定值key的映射f(key),若查找集合中存在这个记录,则必定在f(key)的位置上。我们把这种对应关系f成为散列函数,又称为哈希(Hash)函数。采用散列技术将记录存储在一块连续的存储空间中,这块连续空间称为散列表或哈希表(Hash-... 阅读详情
1. 哈希是一种算法,哈希表是用哈希算法构造出来的一种数据结构
2. 哈希算方法的几种方法
  • 直接定值法
这里有一个例题,就是我们想判断某一字符串中,某一个字符出现的个数,我们可以使用哈希的思想,就是可以遍历一遍字符串,然后开辟一个拥有26数据的整型数组,然后初始化全部为0,然后统计利用一种映射的思想,遍历字符串的时候,就把相应的位置++,每次我们查找某一个字符的时候,一下子就可以定值到那个字符的位置
还有一个例子就是,比如让我们存储1-10这个区间的不重复的数据,这个时候我么也是开辟一个拥有十个元素的整型数组,然后每个数据对应给位置,这样我们在查找的时候,就可以直接查找到这个数据是否存在。
第三个例子是,这里有一些 数据,比如是1001,1006,1009,1007这个时候我们知道数据的范围,我们也是可以开辟一个存储空间来存放这个数据,只不过这个时候我们不需要开辟1000多个大小的数组,我么只需要开辟十个即可,上面的每个数据都减去1000,然后在存放在这个位置,然后我们读取的时候也是按照这个规则读取
分析:上面的几种都是特殊的简单的情况,太具有局限性,还有就是如果我们的数据跨度很大的话,要开辟很大的存储空间,这显然是不合适的,但是一种解题的思路
  • 除留取余法
这里有一部分数据然后我们不能开辟所有的大小的空间,这个时候我呢就出现了一个除留取余法,我们的可以把数据都取余数组的长度,然后放置在相应的位置上面去。
致命缺点:哈希冲突,即是我们的数据可能映射的位置是同一个位置。
法一:闭散列法--开放地址法
(1)第一种方式是线性探测
其他的发生冲突的数据直接往后面走,直到有一个位置上面的数据为空,这个时候把数据放置上去。
比如我么的数据,有89,18,49,58,9,我们开辟的整型数组的空间空间时十个,然后我们放置89,89%10 = 9,然后把89放置在了第九个位置上面去,接着是放置18,18被放置在了8这个位置上面。然后拿到49的时候,我们的数据9这个位置已经后数据,这个时候,我们依次往后走,知道扎到了0号位置是空的,于是49被放置在了0这个位置上面去了。同样 的方法放置其他的数据。
数据放置好了之后,就是查找数据了,这个是时候,如果找9,首先定位到9这个位置上面上,然后没有找到,然后就是依次往后面找,知道找到9,或者就是找到一个空位置停止,这个时候 是没有找到相关的数据。
但是这种方式留下了一个问题就是,如果我们冲突的数据都是集中在了9这个位置了,那每次查找的时候是不是很麻烦,这个时候我我们采用的方法及时二次探测。
(2)第二种方式是二次探测
二次探测的方式值这样的,89进来的时候还是直接放置数据,但是当49进来的时候,不是直接往后面放置了,而是往后移动1的平方个位置,如果是空的就是直接放置,如果不是空的,就是相对于起始位置移动2的 平方个,依次类推下去,直到有一个位置为空。
第一个问题:我们既然已经知道了一次探测的冲突比较大,所以我们这里直接采用的是二次探测
第二个问题:我们的考虑使用数组,但是因为后面的数据可能会增加的很大,所以我们还会考虑增容的操作,这个时候我们不妨直接使用vector。
第三个问题:我们一开始的时候,初始化的时候,初始值应该是多少呢,大家可能和自然的想到了是0,但是有一个问题就是,但是如果我要找的数据就是0的,那不是GG了,所以我们在设计类的成员变量的时候的时候,vector里面的内容 可以放置的是一个结构体,结构体的一部分是数据,一部分是标识位,标识我们的这个位置上面有没有数据
第四个问题:我们既然有增加数据,就一定有删除数据,那个如果是上面的例子,我现在删除了一个数据是49,然后我接下来可能是要找9,这个时候首先定位到下标为9的这个位置,然后往后面二次探测1的平方,这个时候找到了49这个 位置,发现是空,就不往下找了,显然这是不符合 我们的要求的,于是我们想设计结构体的时候,这个标识位有三个值,一个标识有数据,一个标识没有数据,一个标识删除数据,于是我们想到了枚举类型。
第五个问题:我们需要考虑的什么时候增容呢,一开始的想法是当vector满了之后再增容 ,可是这种增容的话,当我们的vector满的 时候是不是数据的冲突就可能大呢,于是我们想的是当已经 放置的数据个数的大小时vector的容量大小的0.7的时候开始增容。
第六个问题:我们的数据在放入的时候,可能在二次探测的时候,可能会出现一只循环在写某些位置,这个 问题下一讲在解决。

代码:hashtable.h
#include<iostream>
using namespace std;
#include<vector>

//作为一个标记位
enum State   
{
	EMPTY,
	EXIT,
	DEL
};


//哈希节点
template<class K,class V>
struct HashNode
{
	pair<K, V> _kv;
	State _state;
	HashNode()
		:_state(EMPTY)
	{
	}
};

template<class K,class V>
ostream& operator<<(ostream &out, HashNode<K,V> node)
{
	out << " "<< " " << node._state;
	return out;
}


template<class K,class V>
class HashTable
{
	//friend ostream& operator<<(ostream &out, HashNode<K, V> node);
public:
	HashTable()
		:_n(0)
	{
		_table.resize(10);  //预留的数租空间大小是
	}

	//插入函数
	bool Insert(const pair<K,V> node)
	{
		Capacity();
		int m = HanshFunc(node);  //HanshFunc,找到我需要插入的一个下标
		size_t index = m;
		size_t i = 0;
		while (_table[index]._state == EXIT)
		{
			index = m;
			i++;
			index = m + i*i;
			while (index >= _table.capacity())
			{
				index = index - _table.capacity();

			}
		}
		_table[index]._kv = node;
		_table[index]._state = EXIT;
		_n++;
		return true;
	}

	int Search(const pair<K, V> node)
	{
		size_t m = HanshFunc(node);
		size_t index = m;
		size_t i = 0;
		while (_table[index]._kv.first != node.first)
		{
			if (_table[index]._state == EMPTY)
			{
				return -1;
			}
			index = m;
			i++;
			index = m + i*i;
			while (index >= _table.capacity())
			{
				index = index - _table.capacity();

			}
		}
		return index;
	}

private:
	void Capacity()
	{
		//if (_n / _table.capacity() >= 0.7)   //这类需要改进的一个地方 就是,我们不能使用0.7,因为除以了之后,不是一个小数
		//{
		//	printf("增容\n");
		//}
		if (_n * 10 / _table.capacity() >= 7)
		{
			printf("增容\n");
		}
	}

	int HanshFunc(const pair<K, V> node)
	{
		size_t index = node.first % _table.capacity();
		
		return index;
	}

private:
	vector<HashNode<K,V>> _table;  //这个是数组
	size_t _n;  //当前放置的数据的个数是多少
};


HashTable.cpp
#define _CRT_SECURE_NO_WARNINGS 1
#include"hashtable.h"

int main()
{
	HashTable<int, int> a;
	pair<int, int> p(5,6);
	pair<int, int> p1(15,7);
	pair<int, int> p2(25, 6);
	pair<int, int> p3(85, 6);
	pair<int, int> p4(75, 6);
	pair<int, int> p5(95, 6);
	pair<int, int> p6(2, 6);
	pair<int, int> p7(4, 6);
	a.Insert(p);
	a.Insert(p1);
	a.Insert(p2);
	a.Insert(p3);
	a.Insert(p4);
	a.Insert(p5);
	a.Insert(p6);
	a.Insert(p7);
	cout << a.Search(p);
	

	return 0;
}


C++哈希表的原理和使用 目录1、概念2、散列表的构造方法2.1、直接定址法 1、概念 散列技术是在记录的存储位置和它的关键字之间建立一个确定的对应关系f,每个关键字key对应一个存储位置f(key),查找时,根据这个对应的关系找到给定值key的映射f(key),若查找集合中存在这个记录,则必定在f(key)的位置上。我们把这种对应关系f称为散列函数,又称为哈希(Hash)函数。采用散列技术将记录存储在一块存储空间中,这块连续空间称为散列表或哈希表(Hash-Table)。 2、散列表的构造方法 2.1、直接定址法 直接定址法使用下 阅读详情

相关推荐

D触发器(D Flip-Flop)与D锁存器(D Latch)

在解释这个练习题之前,我们先来简单回顾一下D触发器(D flip-flop)和D锁存器(D latch)的概念,以及它们在数字电路中的作用。这将帮助我们理解所提到的练习。

weixin_65190179的博客 9170

除留余数法学习

除留余数法介绍 除留余数法此方法为最常用的构造散列函数方法。对于散列表长为m的散列函数公式为: f( key ) = key mod p ( p ≤ m ) mod是取模(求余数)的意思。事实上,这方法不仅可以对关键字直接取模,也可在折叠、 平方取中后再取模。 一个例子   很显然,本方法的关键就在于选择合适的p, p如果选得不好,就可能会容易产生同义词。   下面我们来举个

qq_36498850的博客 1万+

从STM32转战小华HC32F448:手把手教你搞定串口复用与超时中断(附完整代码)

本文详细介绍了从STM32迁移到小华HC32F448的串口开发实战指南,重点解析了HC32F448的GPIO复用系统和超时中断机制。通过对比STM32的架构差异,提供了完整的串口配置代码和优化方案,帮助开发者快速掌握HC32F448的串口通信技术,适用于工业控制等应用场景。

weixin_30564901的博客 549

哈希表的查找(按照除留余数法设计一个哈希函数)

给定一组查找关键字(32,15,7,11,4,28,56,61,79),哈希表长为m=12,请按照除留余数法设计一个哈希函数,设每个记录的查找概率相等。 (1)画出按照线性探测再散列处理冲突得到的哈希表(给出求解过程),并计算等概率情况下查找成功和查找失败时的平均查找长度各是多少。 (2)画出按照链地址法处理冲突得到的哈希表,并计算等概率情况下查找成功和查找失败时的平均查找长度各是多少。 ==设计哈希函数为 == H(key)= key % 11 (1)按照线性探测再散列处理冲突 查找成功时平均查找长度

小小本科生 8054

SAP 接口测试操作-业务顾问

业务顾问测试接口操作

weixin_43657667的博客 5158

kettle9.0+ 连接Hadoop报错

kettle bug

x²+(y-√³x²)²=1的博客 1559

C++数据结构:哈希 -- unordered系列容器、哈希表的结构以及如何通过闭散列的方法解决哈希冲突

本文介绍了unordered系列的容器以及哈希的结构,并讲解了如何通过闭散列的方法解决哈希冲突然后进行了模拟实现

weixin_43908419的博客 2454

C# typeof() 和 GetType()区别

总得来说他们都是为了获取某个实例具体引用的数据类型System.Type。 1、GetType()方法继承自Object,所以C#中任何对象都具有GetType()方法,x.GetType(),其中x为变量名,由x实例返回得到一个类型 2、typeof(x)中的x,必须是具体的类名、类型名称等,不可以是变量名称,返回一个类型 3、System.Type.GetType(),有两个重载方法 比如有这样一个变量i: Int32 i = new Int32(); 使用GetType(),i...

Peter的博客 1956

哈希算法及应用【学习笔记】

好久没写博客了,最近在找工作,把找工作中遇到的问题在这里记录一下,也当是放个松吧,后面估计会开算法、数据结构、操作系统、计算机网络、数据库几个专题吧,把面试过程中学到的东西都记录一下,这篇就主要记录一下Hash相关的知识。这篇主要记录一下什么是哈希,哈希有什么用,哈希怎么实现,七七八八的东西。 一、哈希是什么 哈希又叫散列,主要通过一个函数将不定长的输入映射成一个定长的输出,这个映射而成的输出又被称为散列值。实际上就是一个函数映射,我们输入的是想进行变换的数据,也就是函数的自变量,它的取值范围是没有限制的,

qq_35775183的博客 886

【华为OD机试真题 新系统】1009、企业内部门的最大层级 | 机试真题+思路参考+代码解析(C++、Java、Py、C语言、JS)

【华为OD机试真题 新系统】1009、企业内部门的最大层级 | 机试真题+思路参考+代码解析(C++、Java、Py、C语言、JS) 华为od机试,华为od机试真题,华为od机试E卷,华为odE卷,华为od机试真题E卷,华为OD,华为OD机试,华为OD机试真题,华为od机考,华为od机试D卷,华为od机试真题D卷,华为od手撕代码,华为od,华为od机试C卷,华为od e卷,华为2026e卷,od机试,2026E卷,华为OD机试E卷,什么是华为od,华为od介绍,全面了解华为od,2026华为od,如何备战

KJ.JK 1417

大学生数学建模赛题解析及优秀论文-2021电工杯A题高铁牵引供电系统运行数据分析及等值建模(附Python代码)

我国是世界上电气化铁路运营里程最长、服役电力机车型号最多、运营最 繁忙的国家。截至 2020年底,我国铁路年消耗电量约800亿千瓦时,约占三峡 年总发电量的 80%。图1为高速铁路牵引供电系统示意图,主要包括牵引变电所、牵引网和动车 组。牵引变电所将 220kV三相电压转换为满足电力机车运行的27.5kV单相电压, 其核心元件是牵引变压器。牵引网由馈线、接触网、钢轨、回流线等组成,完成 对电力机车的送电任务。...

wenyusuran的专栏 3169

哈希表的简单理解

哈希表的简单理解一、哈希表简介二、哈希表的映射方式1、直接定值法2、除留余数法2.1、负载因子a2.2、哈希冲突三、哈希表种类1、闭散列1、开散列 一、哈希表简介      哈希(散列)表可以看成一个数组,在存入数值或元素的时候通过映射关系,找到数组对应的位置就可以将元素存入数组中,这样在不存在哈希冲突情况下,查找该元素的效率为O(1)。 二、哈希表的映射方式 1、直接定值法      如上图所示,直接定值

a15980352273的博客 786

STM32入门教程:WiFi通信

第四步:初始化串口 在生成的代码中,您可以找到一个名为 "USARTx_Init" 的函数,其中 "x" 是您选择的串口号。然后,我们使用 "AT+CIPSEND" 命令发送UDP数据,接收到服务器的回复,并在终端上显示收到的数据。在配置向导中,您可以选择启用USART串口功能,并根据您的硬件连接,将串口设置为与WiFi模块连接的串口。在上述代码中,我们使用了 "HAL_UART_Receive" 函数来接收串口数据,并使用 printf 来在终端上显示收到的数据。如果有任何问题,请随时向我提问。

2401_85258012的博客 1075

数据结构——哈希详解

顺序表/链表有一个共同特征,数据值本身和其存储位置之间是没有关系的,所以我们要查找/搜索一个值,只能一个一个的去比较,时间复杂度是O(n),我们想把时间复杂度降下来,提供一种技术让我们数据值本身和存储关系之前有映射关系,这时我们查找值是否存在则直接根据这种映射关系计算得出其存储位置,这时只去要去计算得出的存储位置查看即可——这种技术就是散列技术也就是哈希,映射关系就是哈希函数f   

weixin_75197906的博客 2996

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

哈希表的相关知识以及使用java实现哈希桶

哈希表是一种高效的数据结构,通过哈希函数建立键值与存储位置的映射关系,实现快速查找。主要介绍了两种哈希表形式:开放地址法和链地址法(哈希桶)。哈希冲突是不可避免的,可通过优化哈希函数设计(如除留余数法)和调整负载因子(建议0.7-0.8)来降低冲突率。重点分析了闭散列(线性探测/二次探测)和开散列两种冲突解决方法,并提供了Java实现哈希桶的完整代码示例,包含插入、扩容和查找操作。代码实现时需注意负载因子计算、头插法处理冲突以及扩容时的重新哈希等关键点。

Z2076465172的博客 1552

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

哈希之开散列和闭散列

目的:实现一种结构,不经过任何比较,一次直接得到想要的元素。通过某种函数使元素的存储位置与它的关键码之间建立一种一一映射的关系。那么就可以在查找时快速的找到需要的元素。 哈希概念 哈希之散列方法: 插入元素时:根据需要插入元素的值,通过某种计算得出元素的存储位置,将该元素插入到其对应的位置。 查找元素时:根据需要查找的元素进行某种计算得到其存储位置,将该位置的元素与查找...

小胡同的诗 630

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

哈希表

哈希表: 概念:构造一种存储结构,通过某种函数关系使元素的存储位置与它的关键码之间建立一种一一对应的映射。 插入: 根据待插入元素的关键码,以此函数计算出该元素的存储位置并按此位置进行存放 搜索元素: 对元素的关键码进行同样的计算,把求得的函数值当做元素的存储位置,在结构中按此位置取元素比较,若 关键码相等,则搜索成功 哈希方法中使用的转换函数称为哈...

qq_44768470的博客 143

哈希表的原理和使用(C++代码)

概念 散列技术是在记录的存储位置和他的关键字之间建立一个确定的对应关系f,是的每个关键字key对应一个存储位置f(key)。查找时,根据这个对应的关系找到给定值key的映射f(key),若查找集合中存在这个记录,则必定在f(key)的位置上。我们把这种对应关系f成为散列函数,又称为哈希(Hash)函数。采用散列技术将记录存储在一块连续的存储空间中,这块连续空间称为散列表或哈希表(Hash-Tab...

hustanding 5万+

哈希相关及C语言实现

散列(哈希): 是在记录的存储位置和它的关键字之间建立一个确定的映射关系f,使得每个关键字key对应一个存储位置(参考大话数据结构8.9-8.12)。 存储位置=f(key)f称为散列函数,又称为哈希函数。采用散列技术将记录存储在一块连续的存储空间中,这块连续存储空间称为散列表或哈希表。 哈希是用来解决查找与给定值相等的位置。 设计一个简单、均匀、存储利用率高的散列函数是散列技术中最关键的问题。 散列冲突:两个key1 != key2,但是f(key1) =...

weixin_37515325的博客 1013

C++学习笔记(二)————哈希表(Hash)

一、哈希表(散列表) 查找领域有三种主要的查找方式,线性表查找,树形查找(类似BST),还有一种就是散列表查找,散列表又叫哈希表。 哈希函数 哈希表 数据记录 哈希表就是我们的函数,对于每一个输入的键值,唯一映射一个存储地址,地址终究存放着我们的数据。 哈希函数是一个映射,设计核心是设计完美的哈希函数尽量减少冲突。 哈希函数:对任意的键值返回出相应的唯一的内存地址以供我们对数据的插入删除和存储 冲突:就像函数中会出现周期函数一样,我们完全也会碰见一种情况就是,针对不同的关键字我们可能会获得相同

冰与火的青春的博客 1694

java 哈希表与HashMap

哈希表的概念 \qquad一种新的存储方式 — 散列技术。 \qquad散列技术是指在记录的存储位置和它的关键字之间建立一个确定的对应关系f,使每一个关键字都对应一个存储位置。即:存储位置=f(关键字)。这样,在查找的过程中,只需要通过这个对应关系f 找到给定值key的映射f(key)。只要集合中存在关键字和key相等的记录,则必在存储位置 f(key)处。我们把这种对应关系f 称为散列函数或哈希函数。 \qquad采用散列技术将记录存储在一块连续的存储空间中,这块连续的存储空间称为哈希表。所得的存储地址称

weixin_45350120的博客 428

链表法实现哈希表(C++实现)

参考博客:https://blog.youkuaiyun.com/weixin_38169413/article/details/81612307 一、概念 散列技术是在记录的存储位置和他的关键字之间建立一个确定的对应关系f,是的每个关键字key对应一个存储位置f(key)。查找时,根据这个对应的关系找到给定值key的映射f(key),若查找集合中存在这个记录,则必定在f(key)的位置上。我们把这种对应关系...

EricLee23 3689

【查找】哈希(散列)查找

散列函数是将关键字映射为表中地址的函数,记为Hash(key)= Addr: 由于散列函数可能将不同关键字映射到同一地址,这种情况叫做冲突。我们希望尽量减少这种冲突,所以需要寻找好的散列函数;同时,冲突是不可避免的,所以还需要设计解决冲突的方法。:映射到同一地址的不同关键字称为同义词。根据关键字直接进行访问的数据结构。

姜略略的博客 1008

散列表基本常识(必知必会·理论篇)

本博文源于浙江大学《数据结构》。散列(Hashing)是一种重要的查找方法。它的基本思想是:以数据对象的关键字key为自变量,通过一个确定的函数关系h,计算出对应的函数值h(key),把这个值解释为数据对象的存储地址,并按此存放,即“存储位置=h(key)”。

执念斩长河 2万+

数据结构与算法之哈希表及实现

传统的查找都是通过"比较"来实现的 . 比如说,顺序查找是"等于"和"不等于"来比较. 改进一些的方法,就是折半查找,二叉排序树,B-树查找,通过">","<","="来比较的.查找的效率依赖于查找过程中所进行的比较次数.这些查找方法元素在结构中的位置是随机的,存在不确定的关系. 最理想的查找的方法就是我们可以根据要查找的元素关键字key...

suoyudong的博客 579
上一篇: 线程互斥和同步-- 互斥锁
下一篇: HTTP项目1.0 -- HTTP协议基础知识
NeilZhy
博客等级 码龄11年 175粉丝 145原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值