散列表C++实现

哈希表与散列表的原理及C++实现 哈希表(Hash Table)是一种高效的数据结构,用于存储键值对(Key-Value Pairs)。它通过哈希函数(Hash Function)将键(Key)映射到一个固定大小的数组(称为散列表)中的某个位置,从而实现快速的插入、查找和删除操作。哈希表的核心思想是通过哈希函数将键转换为数组的索引,从而直接访问对应的值。理想情况下,哈希表的插入、查找和删除操作的时间复杂度都是O(1)。哈希表是一种高效的数据结构,通过哈希函数将键映射到数组索引,从而实现快速的插入、查找和删除操作。 阅读详情

散列表

散列表是一种查找技术,通俗一点说就是无需任何比较,直接通过关键码便能得到待查记录的存储位置。原理就必须在记录的存储位置和它的关键码之间建立一个确定的对应关系H,使得每个关键码key和惟一的一个存储位置H(key)相对应。在查找时,根据这个确定的对应关系找到给定值k的映射H(k),若查找集合中存在这个记录,则必定在H(k)的位置上。

这里的关键码可以看成你要查找的东西,比如整数23存储在哈希表的数组中,那么关键码就是整数23

也就是说我们仅需要这个关键码进行某种操作,就能得到它在哈希表数组内的下标,这样我们就无需遍历整个哈希表数组了。

散列表类定义

这里仅实现了线性探查法的搜索,插入,删除以及二次探查法的搜索,即FindPos2,二次探查法的插入就不编了,就是散列表的长度要符合4k+3的质数定义,以及里面的装载因子要小于0.5。

二次探查法相对于线性探查法,解决了数据堆积的问题,个人感觉主要是二次探查法每次插入进行的变化是+1,-1,+4,-4....都是平方变化,这样就让数据分散的比较均匀,用空间换取查找速度。

enum NodeInfo { Empty, Active, Delete };//记录节点的状态

template<typename K>
class HashTable
{
public:
	HashTable(int d,int sz= DefaultSize);
	~HashTable();
	void PrintValue();

	bool Search(const K& k);//查看键码k是否存在
	bool Insert(const K& k);//插入键码k
	bool Remove(const K& k);//删除键码k

private:

	int FindPos1(const K& k)const;//寻找键k在哈希表的存储数组中对应的位置,使用线性探查法
	int FindPos2(const K& k)const;//寻找键k在哈希表的存储数组中对应的位置,使用二次探查法

	int curSize, maxSize;//curSize存储当前哈希表存储节点的数量,maxSize为哈希表最多存储的节点的数量
	NodeInfo* info;//存储每个节点的状态数组,作为辅助数组
	int divitor;//散列表的除数
	K* value;//哈希表的存储节点的数组
};

线性探查法

需要注意的是寻找下一个桶的下标是通过j = (j + 1) % maxSize完成的。

//寻找键k在哈希表的存储数组中对应的位置,使用线性探测法
template<typename K>
int HashTable<K>::FindPos1(const K& k) const
{
	int i = k % divitor;
	if (info[i] == Empty) return -1;//如果info状态为空,那么该键码不存在哈希表中
	int j = i;//j作为移动的指针
	do
	{
		if (info[j] == Active && value[j] == k) return j;//如果节点转态为Active,且value数组在j处值为k
		j = (j + 1) % maxSize;//位移
	} while (j != i);
	return -1;
}

二次探查法

需要注意,每次while循环仅移动一次,比如+1,-1,+4,-4,需要进行四次循环,并且在+1,-1中这两次循环中i是相同的(第二次使用的是save,保存了上一次i的数值)

//寻找键k在哈希表的存储数组中对应的位置,使用二次探查法
template<typename K>
int HashTable<K>::FindPos2(const K& k) const
{
	int i = k % divitor;
	int flag = 0;//控制加减号,由于每次进进行移动时+1,-1,+4,-4.....
	int save, j = 0;//j代表每次递增进位
	while (info[i] == Delete || info[i] == Active && value[i] != k)//每次循环flag变化一次
	{
		if (flag == 0)
		{
			save = i;//保存此时的i值,下次循环时时使用
			j++;
			i = (i + 2 * j - 1) % maxSize;//2*j-1,是+1变成+4需要增加增量,这里不使用平方,平方耗时
			i = (i < 0) ? (i + maxSize) : i;//当i为0时,第一次循环时i会变为负值,将其变为正值
			flag = 1;
		}
		else
		{
			i = (save - 2 * j + 1) % maxSize;
			i = (i < 0) ? (i + maxSize) : i;
			flag = 0;
		}
	}
	if (info[i] == Empty) return -1;
	else if(value[i] == k) return i;
}

全部代码

HashTable.h

#pragma once
#ifndef HASHTABLE_H
#define HASHTABLE_H
#include<iostream>
#include<cassert>
const int DefaultSize = 128;
using std::cout;
using std::endl;

enum NodeInfo { Empty, Active, Delete };//记录节点的状态

template<typename K>
class HashTable
{
public:
	HashTable(int d,int sz= DefaultSize);
	~HashTable();
	void PrintValue();

	bool Search(const K& k);//查看键码k是否存在
	bool Insert(const K& k);//插入键码k
	bool Remove(const K& k);//删除键码k

private:

	int FindPos1(const K& k)const;//寻找键k在哈希表的存储数组中对应的位置,使用线性探查法
	int FindPos2(const K& k)const;//寻找键k在哈希表的存储数组中对应的位置,使用二次探查法

	int curSize, maxSize;//curSize存储当前哈希表存储节点的数量,maxSize为哈希表最多存储的节点的数量
	NodeInfo* info;//存储每个节点的状态数组,作为辅助数组
	int divitor;//散列表的除数
	K* value;//哈希表的存储节点的数组
};


#endif // !HASHTABLE_H

template<typename K>
HashTable<K>::HashTable(int d, int sz)
{
	divitor = d;
	maxSize = sz;
	curSize = 0;
	value = new K[maxSize];
	info = new NodeInfo[maxSize];
	assert(value && info);
	for (int i = 0; i < maxSize; i++)//所有节点状态都设为空
		info[i] = Empty;
}

template<typename K>
HashTable<K>::~HashTable()
{
	if (value) delete[] value;
	if (info) delete[] info;
}

template<typename K>
void HashTable<K>::PrintValue()
{
	for (int i = 0; i < maxSize; i++)
	{
		if (info[i] == Active) cout << value[i] << " ";
		else cout << 0 << " ";
	}
	cout << endl;
}

//查看键码k是否存在
template<typename K>
bool HashTable<K>::Search(const K& k)
{
	if (FindPos1(k) >= 0)
		return true;
	return false;
}

template<typename K>
bool HashTable<K>::Insert(const K& k)
{
	if (FindPos1(k) >= 0) return false;
	int i = k % divitor;
	int j = i;//j作为移动的指针
	do
	{
		if (info[j] == Empty) {//当节点状态为空时,进行插入,否则j将一直移动下去
			value[j] = k;
			info[j] = Active;
			curSize++;
			return true;
		}
		else
			j = (j + 1) % maxSize;
	} while (j != i);
	return false;
}

template<typename K>
bool HashTable<K>::Remove(const K& k)
{
	int x = FindPos1(k);
	if (x < 0) return false;
	else {
		info[x] = Delete;
		curSize--;
		return true;
	}
}

//寻找键k在哈希表的存储数组中对应的位置,使用线性探测法
template<typename K>
int HashTable<K>::FindPos1(const K& k) const
{
	int i = k % divitor;
	if (info[i] == Empty) return -1;//如果info状态为空,那么该键码不存在哈希表中
	int j = i;//j作为移动的指针
	do
	{
		if (info[j] == Active && value[j] == k) return j;//如果节点转态为Active,且value数组在j处值为k
		j = (j + 1) % maxSize;//位移
	} while (j != i);
	return -1;
}

//寻找键k在哈希表的存储数组中对应的位置,使用二次探查法
template<typename K>
int HashTable<K>::FindPos2(const K& k) const
{
	int i = k % divitor;
	int flag = 0;//控制加减号,由于每次进进行移动时+1,-1,+4,-4.....
	int save, j = 0;//j代表每次递增进位
	while (info[i] == Delete || info[i] == Active && value[i] != k)//每次循环flag变化一次
	{
		if (flag == 0)
		{
			save = i;//保存此时的i值,下次循环时时使用
			j++;
			i = (i + 2 * j - 1) % maxSize;//2*j-1,是+1变成+4需要增加增量,这里不使用平方,平方耗时
			i = (i < 0) ? (i + maxSize) : i;//当i为0时,第一次循环时i会变为负值,将其变为正值
			flag = 1;
		}
		else
		{
			i = (save - 2 * j + 1) % maxSize;
			i = (i < 0) ? (i + maxSize) : i;
			flag = 0;
		}
	}
	if (info[i] == Empty) return -1;
	else if(value[i] == k) return i;
}

main.cpp

#include"HashTable.h"


int main()
{
	HashTable<int> myhash(11, 12);
	int a[] = { 37,25,14,36,49,68,57,11 };
	for (int i = 0; i < sizeof(a) / sizeof(int); i++)
		myhash.Insert(a[i]);
	myhash.PrintValue();
	return 1;
}

 

数据结构:散列表(哈希表)开放定址法原理及C++实现 前言:        最近写了下RabinKarp算法,当中使用到了一定的Hash方法,我顺就复习了一下Hash表的实现原理,要不然感觉自己都要忘记了~~原理:散列表:        散列表也称哈希表,是一种键值对应的数据结构(key-value),也就是说任何一个存储在Hash表中的数据(value)都会有一个对应的键值(key)用来存储它。我们可以这样来理解他:在我们去电影院看电影的时候,我们... 阅读详情

相关推荐

c++,散列表的实现

散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。

第99篇 C++数据结构(九)散列表

第99篇 C++数据结构(九)散列表1.散列表简介1.1.散列函数1.2.散列冲突解决方案2.数据节点3.实现3.1.变量3.2.方法4.测试4.1.测试代码4.2.输出结果5.实现代码6.总结 详细介绍: 大佬文章链接1 大佬文章链接2 1.散列表简介 散列表也叫哈希表(Hash table),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。 1.1.散列函数 散列函

weixin_49188222的博客 2423

Verilog单周期CPU设计(超详细)

实验 单周期CPU一、设计目的与目标实验内容实验要求二、课程设计器材硬件平台软件平台三、 CPU逻辑设计总体方案指令模块MIPS指令格式指令处理流程数据通路总体结构图设计流程逻辑图四、模块详细设计PCAdd4PCINSTMEMDATAMEMSHIFTER32_L2SHIFTER_COMBINATIONMUX4X32MUX2X5EXT16T32MUX2X32CONUNITREGFILEALUSing...

Ace Cheney的博客 9万+

哈希表(散列表)C/C++代码实现

哈希表(散列表): 1,构造散列函数 最常用的方法是除留余数法: H(key) = key%p 这个方法的关键是选取适当的p, 一般情况下,可以选p为小于表长的最大质数。例如表长m=100, 可取p=97。 2,处理冲突 选择一个 “好” 的散列函数可以在一定程度上减少冲突,但在实际应用中,很难完全避免发生冲突 1,开放地址法 (1)线性勘测法 (2)二次探测法 (3)伪随机探测法 线性探测法的优点是:只要散列表未填满,总能 找到一个不发生冲突的地址。缺点是:会产生 ”二次聚集“ 现象。而二次探测法和伪随机

Ycy的博客 1万+

VTK基础教程(1)- vtkPolyData 介绍

目录 VTK的编译与环境搭建 VTK一般渲染流程 VTK数据类型-vtkPolyData 使用vtk自带的多边形数据 使用自己创建的数据 添加顶点颜色 添加面颜色 VTK的编译与环境搭建 这部分目前已经有了大佬做了成熟的傻瓜式配置,大家可以参考这篇文章:VTK+VS2019(或其他版本均可) 傻瓜式一站式 配置_Nancy_fairy的博客-优快云博客_vs2019 vtk VTK一般渲染流程 这部分的介绍也很多,大家可以参考这篇文章:VTK笔记-了解VTK_黑山老妖的博客.

qq_35769071的博客 9052

从零到一:手把手部署用友T3标准版11.2及SQL Server 2008R2环境

本文详细介绍了从零开始部署用友T3标准版11.2及SQL Server 2008R2环境的完整流程,包括环境准备、SQL Server安装、环境检测与修复、T3标准版安装实战以及初始化配置与测试。通过手把手的步骤指导和常见问题解决方案,帮助用户顺利完成部署,确保系统稳定运行。

weixin_28339967的博客 452

散列技术-散列表的概念

散列方法不同于顺序查找、二分查找、二叉排序树及B-树上的查找。它不以关键字的比较为基本操作,采用直接寻址技术。在理想情况下,无须任何比较就可以找到待查关键字,查找的期望时间为O(1)。 散列表的概念 1、散列表  设所有可能出现的关键字集合记为U(简称全集)。实际发生(即实际存储)的关键字集合记为K(|K|比|U|小得多)。  散列方法是使用函数h将U映射到表T[0..m-1]的下

Code-lover's Learning Notes 953

camera 知识速查

本文总结了Camera开发中的常见问题排查方法和关键技术点。主要内容包括:I2C/MIPI不通的排查步骤、时序问题分析方法、Sensor/AF/Flash/PDAF的Bring Up流程、OTP调试方法、PDAF原理及调试、CTS/ITS问题解决思路、AE震荡解决方案、Systrace性能分析方法、Flicker产生原理、Tombstone问题定位等。还涉及V4L2框架解析、问题定位分层方法、Sensor Setting注意事项、时钟信号概念、第三方应用卡顿排查、大光圈概念、Monkey测试方法。

qq_41665131的博客 783

c++实现哈希查找(散列表)

使用除留余数法构造哈希函数 使用线性探测法来解决冲突 #include<iostream> using namespace std; const int MAX = 65535; //设置一个不可能输入的值 //建立哈希表 void Creat_HashTable(int *arr, int num) { int x = 0, key = 0; // x 为将要输入的值, key 为键值下标 //初始化哈希表为MAX for (int i = 0; i < num; i++)

orange_monkey的博客 769

TC3XX - MCAL知识点(九):PWM EB-tresos配置说明及代码浅析

脉冲宽度调制(PWM)驱动器负责提供与AUTOSAR指定的PWM信号生成相关的标准服务。PWM通道的底层定时器驱动是GTM (TOM或ATOM片)或CCU6 (T12或T13片)定时器通道。软硬件匹配关系如下:PWM直接引用的是GTM与CCU6模块,然后GTM与CCU6再关联到Port的,根据软硬件匹配关系,也能调用中断来使用,本例子没使用中断。CCU6是一个高分辨率的16位捕获和比较单元,具有特定的应用模式,主要用于交流驱动控制。特殊的工作模式支持控制无刷直流电机使用霍尔传感器或反电动势检测。

梦想技术家 2882

手把手教你学Simulink--基于飞轮储能系统的场景实例:飞轮储能与锂电池混合储能系统的协同控制

本文详细介绍了基于Simulink的飞轮储能与锂电池混合储能系统协同控制建模方法。通过高通/低通滤波器实现功率分配,使飞轮处理高频波动(±100kW),锂电池承担削峰填谷(50kW)。仿真结果表明,该系统效率达88%,锂电池循环次数减少90%,投资成本比纯电池方案节省200万美元。文章包含完整的建模步骤、控制策略设计和多场景仿真分析,为构建高效、长寿、经济的智能储能系统提供了实用解决方案。

MHD0815的博客 341

[C++]数据结构:散列表HashTable的实现与简单应用

#include &lt;iostream&gt; using namespace std; template&lt;class E,class K&gt; class HashTable{ public: HashTable(int divisor=11); ~HashTable(){delete[]ht;delete[]empty;} ...

thewebcode 255

合肥工业大学嵌入式系统原理实验报告

GPKDAT 的6、7引脚设置低电平,设置GPKDAT = 0x30则34灯亮12灯灭,GPKDAT 的4、5、6、7引脚全为高电平,设置GPKDAT = 0xf0,则led灯全灭。注意在烧写时要连接主机后面的USB接口,烧写完成后,要关闭开发板电源,将S2拨动开关置于NAND位置,然后重新开启开发板电源, 则开发板运行刚刚烧入的裸机程序。实验修改要求:在延时不变的条件下,将原程序中四个LED全亮,然后全灭的显示状态,修改为“四个全亮,然后1和2亮(3和4灭),然后3和4亮(1和2灭),最后全灭”。

Martin-share的博客 3097

【C++】模拟实现hash_table(哈希表)

使用C++语言模拟实现开链法哈希表,包括实现HashNode类模板,实现hashTable构造函数,析构函数,插入函数,查找函数,删除等函数详解.

C/C++领域,数据结构,linux,MySQl学习者 1788

把 SAP Workflow 的 Task 搞懂:从 TS 到 WS 的建模、触发与排错全景

摘要:SAP Business Workflow中的Task是工作流设计的核心单元,分为single-step(独立执行)和multistep(流程编排)两种类型。Task设计直接影响流程的可复用性、扩展性和可排错性。系统将Task分为5类(TS/T/WS/WF/TG),运行时通过事件触发、Linkage匹配、Work Item执行的链路完成流程驱动。关键事务码包括PFTC_INS(创建Task)、SWE2(事件配置)等。正确设计Task边界并遵循"先业务提交后事件触发"原则,是构建稳定

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 272

假人有限元模型

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

哈希表(散列表) C++实现

文章目录哈希函数哈希函数的构造方法处理散列冲突的方法散列表性能分析散列表C++代码实现 哈希函数 哈希函数就是 关键字Key 到 值Value 的映射: Value = f(Key) Value反映的是关键字Key的存储地址。 哈希函数的构造方法 直接定址法 f(Key) = a * Key + b 例如存放不同出生年份的人口数量,出生年份是关键字,那么可以用直接定址法。 直接定址法的优点是简单均匀,也不会产生冲突;缺点是该方法适合表比较小且连续的情况,所以 该方法虽然简单但是并不常用。 数

Worthy_Wang的博客 1847

android 蓝牙通讯demo

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

C++ 哈希表实现

什么叫做哈希表?相信大家在很多地方都听过哈希表这三个字。在之前,我看到java之父余胜军装小白面试的时候,对哈希表那是侃侃而谈,非常的羡慕他对哈希表的理解,在学习哈希表过后,我发现他的难度还不一定比得上红黑树,那让我们今天来揭开哈希表的神秘面纱。哈希表跟set和map结构类似,库函数如果是unordered_set,那就是Key模型库函数如果是unordered_map,那就是Key,Value模型。表我们很容易理解,那么什么是哈希?

kkbca的博客 1509

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

C++中的unordered_set,unordered_map,哈希表/散列表以及哈希表的模拟实现

本节首先介绍了unordered_set和unordered_map,然后借此引出了哈希/散列和哈希表/散列表的概念;然后着重分析了哈希表这一数据结构,提到了哈希函数和哈希冲突处理方法这两个概念,再分别介绍了常用的哈希函数:直接定址法和除留余数法,常用的哈希冲突处理:闭散列开放定址法(线性探测,二次探测)和开散列哈希桶法,同时就如何支持多种类型的key来使用的问题,以string为例进行了详细分析

tianxhiliangtadi的博客 1293

哈希表C++实现--hash_table

1、hash_table.h #include 3 #include 4 #include 5 #include 6 #include 7 using namespace std; 8 9 struct table_node 10 { 11 int _key; 12 string _value; 13 struct tabl

zhou753099943的专栏 5826

链接法(chaining)构建散列表(hash table)(C++实现)

散列表(Hash table,也叫哈希表),是根据关键字(Key value)而直接访问在内存存储位置的数据结构。也就是说,它通过把键值通过一个函数的计算,映射到表中一个位置来访问记录,这加快了查找速度。这个映射函数称做散列函数,存放记录的数组称做散列表。 一个通俗的例子是,为了查找电话簿中某人的号码,可以创建一个按照人名首字母顺序排列的表(即建立人名x到首字母F(x)的一个函数关系),在首

hustyangju的足迹 4297

散列表/哈希表(hash table)- C++实现

散列表又称哈希表,查找只需要花费常数时间,查找效率极高,对庞大数据的查找很有作用。 散列表解决冲突的方式有多种,这里采用了分离链接法,除此外还有开放地址法和双散列。 Vocabulary类是用来储存单词的类,用于实现一个离线词典的数据方案,当然这并不是最高效的方法,但是我认为是比较容易理解的方法,对于初学哈希表的人来说还是比较容易接受的。 1 /*******************...

weixin_34162401的博客 298

【C++】哈希表的实现

与闭散列的哈希表不同的是,在实现开散列的哈希表时,我们不用为哈希表中的每个位置设置一个状态字段,因为在开散列的哈希表中,我们将哈希地址相同的元素都放到了同一个哈希桶中,并不需要经过探测寻找所谓的“下一个位置”。与闭散列不同的是,这种将相同哈希地址的元素通过单链表链接起来,然后将链表的头结点存储在哈希表中的方式,不会影响与自己哈希地址不同的元素的增删查改的效率,因此开散列的负载因子相比闭散列而言,可以稍微大一点。的时候,这时发现,如果我们已同样的方法进行插入的时候,就会与 1 下标位置的元素起到冲突。

wh9109的博客 1043

C++哈希表的实现

C++哈希表的实现

Wzs040810的博客 6552

C++实现哈希表

本文主要是对哈希表这种数据结构进行介绍。含义是根据存储的值和存储的位置建立映射关系从而快速检索查找存储的数据,哈希表是一种非常高效的数据结构。本文会用C++介绍哈希表的相关实现。

Ly的博客 3260

[AcWing]840. 模拟散列表(C++实现)哈希表模板题

[AcWing]840. 模拟散列表(C++实现)哈希表模板题)1. 题目2. 读题(需要重点注意的东西)3. 解法4. 可能有帮助的前置习题5. 所用到的数据结构与算法思想6. 总结 1. 题目 2. 读题(需要重点注意的东西) 思路:开放寻址法 3. 解法 注: find(int x)的作用是: 如果x在哈希表中存在,那么返回x在哈希表中的位置; 如果x在哈希表中不存在,那么应该返回它应该在哈希表中存储的位置。 -------------------------------------------

cloud的博客 851

C++简单实现hash table

哈希表(Hash Table,又称为散列表)是根据关键字(key)来直接访问在内存存储位置的一种数据结构。与循”值”访问对应的访问方式是循”址”访问,如数组、向量vector等。 哈希函数(Hash Function):通过一个映射函数,将键值映射到存储位置来访问元素,这能加快查找速度。这个映射函数称哈希函数(散列函数)。 举例 电话薄查找号码:为了查找电话簿中某人的号码,可以创建一个按照人

big_lobster的专栏 7148
上一篇: 并查集C++实现
下一篇: mask图像获取物体标注框(仅限一张图片一个物体)
-Gentle-
博客等级 码龄8年 80粉丝 16原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值