Hash表的C++实现(转)
原文:Hash表(C++实现)
哈希表的几个概念:
映像:由哈希函数得到的哈希表是一个映像。
冲突:如果两个关键字的哈希函数值相等,这种现象称为冲突。
处理冲突的几个方法:
1、开放地址法:用开放地址处理冲突就是当冲突发生时,形成一个地址序列,沿着这个序列逐个深测,直到找到一个“空”的开放地址,将发生冲突的关键字值存放到该地址中去。
例如:hash(i)=(hash(key)+d(i)) MOD m (i=1,2,3,......,k(k<m-1)) d为增量函数,d(i)=d1,d2,d3,...,dn-1
根据增量序列的取法不同,可以得到不同的开放地址处理冲突探测方法。
有线性探测法、二次方探测法、伪随机探测法。
2、链地址法:把所有关键字为同义词的记录存储在一个线性链表中,这个链表成为同义词链表,即把具有相同哈希地址的关键字值存放在同义链表中。
3、再哈希表:费时间的一种方法
下面是代码:
文件"myhash.h"
#include<iostream>
using namespace std; typedef int KeyType; //设关键字域为整形,需要修改类型时,只需修改这里就可以
const int NULLKEY=; //NULLKEY表示该位置无值
int c=; //用来统计冲突次数 struct Elemtype //数据元素类型
{
KeyType key;
int ord;
}; int hashsize[]={,,,,}; //hash表容量递增表
int Hash_length=;//hash表表长 class HashTable
{
private:
Elemtype *elem; //数据元素数组,动态申请
int count;// 当前数据元素个数
int size; //决定hash表的容量为第几个,hashsize[size]为当前hash容量
public: int Init_HashTable() //构造一个空hash表
{
int i;
count=;
size=; //初始化容量为hashsize[0]=11
Hash_length=hashsize[];
elem=new Elemtype[Hash_length];
if(!elem)
{
cout<<"内存申请失败"<<endl;
exit();
}
for(i=;i<Hash_length;i++)
elem[i].key=NULLKEY;
return ;
} void Destroy_HashTable()
{
delete[]elem;
elem=NULL;
count=;
size=;
} unsigned Hash(KeyType k) //hash函数的一种(取模法)
{
return k%Hash_length;
} void Collision(int &p,int d) //解决冲突
{
p=(p+d)%Hash_length; //采用开放地址法里的线性探测
} bool Search_Hash(KeyType k,int &p) //查找
{
//在开放地址hash表中查找关键字等于k的元素
//若找到用p表示待查数据,查找不成功时,p指向的是可插入地址
c=;
p=Hash(k); //求hash地址
while(elem[p].key!=NULLKEY && elem[p].key!=k)
{
c++;
if(c<Hash_length)
Collision(p,c);
else
return ; //表示查找不成功
}
if(elem[p].key==k)
return ;
else
return ; } int Insert_Hash(Elemtype e) //插入
{
//在查找不成功的情况下将k插入到hash表中
int p;
if(Search_Hash(e.key,p))
return -; //表示该元素已在hash表中
else if(c<hashsize[size]/) //冲突次数未达到上限
{
//插入e
elem[p]=e;
count++;
return ;
}
else
ReCreate_HashTable(); // 重建hash表
return ; //插入失败
} void ReCreate_HashTable() //重建hash表
{
int i,count2=count;
Elemtype *p,*elem2=new Elemtype[count];
p=elem2;
cout<<"____重建hash表_____"<<endl;
for(i=;i<Hash_length;i++) //将原有元素暂存到elem2中
if(elem[i].key!=NULLKEY)
*p++=*(elem+i);
count=;delete []elem;
size++; //hash容量增大
Hash_length=hashsize[size];
p=new Elemtype[Hash_length];
if(!p)
{
cout<<"空间申请失败"<<endl;
exit();
}
elem=p;
for(i=;i<Hash_length;i++)
elem[i].key=NULLKEY;
for(p=elem2;p<elem2+count2;p++) //将原有元素放回新表
Insert_Hash(*p);
} void Traverse_HashTable()
{
cout<<"哈希地址0->"<<Hash_length-<<endl;
for(int i=;i<Hash_length;i++)
if(elem[i].key!=NULLKEY)
cout<<"元素的关键字值和它的标志分别是:"<<elem[i].key<<" "<<elem[i].ord<<endl; } void Get_Data(int p)
{
cout<<"元素的关键字值和它的标志分别是:"<<elem[p].key<<" "<<elem[p].ord<<endl;
} };
测试函数"main.cpp"
#include"myhash.h" int main()
{
Elemtype r[]={{,},{,},{,},{,},{,},{,},{,},{,},{,},{,},{,},{,}};
HashTable H;
int i,p,j;
KeyType k;
H.Init_HashTable();
for(i=;i<;i++) //插入前11个记录
{
j=H.Insert_Hash(r[i]);
if(j==-)
cout<<"表中已有关键字为"<<r[i].key<<" "<<r[i].ord<<"的记录"<<endl;
} cout<<"按哈希地址顺序遍历哈希表"<<endl;
H.Traverse_HashTable();
cout<<endl; cout<<"输入要查找的记录的关键字:";
cin>>k;
j=H.Search_Hash(k,p);
if(j==)
H.Get_Data(p);
else
cout<<"无此记录"<<endl; j=H.Insert_Hash(r[]); //插入最后一个元素
if(j==)
{
cout<<"插入失败"<<endl;
cout<<"需要重建哈希表才可以插入"<<endl;
cout<<"____重建哈希表____"<<endl;
H.Insert_Hash(r[i]); //重建后重新插入
} cout<<"遍历重建后的哈希表"<<endl;
H.Traverse_HashTable();
cout<<endl; cout<<"输入要查找的记录的关键字:";
cin>>k;
j=H.Search_Hash(k,p);
if(j==)
H.Get_Data(p);
else
cout<<"该记录不存在"<<endl; cout<<"____销毁哈希表____"<<endl;
H.Destroy_HashTable(); return ;
}
测试结果:
按哈希地址顺序遍历哈希表
哈希地址0->
元素的关键字值和它的标志分别是:
元素的关键字值和它的标志分别是:
元素的关键字值和它的标志分别是:
元素的关键字值和它的标志分别是:
元素的关键字值和它的标志分别是:
元素的关键字值和它的标志分别是:
元素的关键字值和它的标志分别是:
元素的关键字值和它的标志分别是:
元素的关键字值和它的标志分别是:
元素的关键字值和它的标志分别是:
元素的关键字值和它的标志分别是: 输入要查找的记录的关键字:
元素的关键字值和它的标志分别是:
____重建hash表_____
插入失败
需要重建哈希表才可以插入
____重建哈希表____
遍历重建后的哈希表
哈希地址0->
元素的关键字值和它的标志分别是:
元素的关键字值和它的标志分别是:
元素的关键字值和它的标志分别是:
元素的关键字值和它的标志分别是:
元素的关键字值和它的标志分别是:
元素的关键字值和它的标志分别是:
元素的关键字值和它的标志分别是:
元素的关键字值和它的标志分别是:
元素的关键字值和它的标志分别是:
元素的关键字值和它的标志分别是:
元素的关键字值和它的标志分别是:
元素的关键字值和它的标志分别是: 输入要查找的记录的关键字:
元素的关键字值和它的标志分别是:
____销毁哈希表____
Press any key to continue
Hash表的C++实现(转)的更多相关文章
- hash表长度优化证明
hash表冲突的解决方法一般有两个方向: 一个是倾向于空间换时间,使用向量加链表可以最大程度的在节省空间的前提下解决冲突. 另外一个倾向于时间换空间,下面是关于这种思路的一种合适表长度的证明过程: 这 ...
- 6.数组和Hash表
当显示多条结果时,存储在变量中非常智能,变量类型会自动转换为一个数组. 在下面的例子中,使用GetType()可以看到$a变量已经不是我们常见的string或int类型,而是Object类型,使用-i ...
- PHP数组/Hash表的实现/操作、PHP变量内核实现、PHP常量内核实现 - [ PHP内核学习 ]
catalogue . PHP Hash表 . PHP数组定义 . PHP变量实现 . PHP常量实现 1. PHP Hash表 0x1: 基本概念 哈希表在实践中使用的非常广泛,例如编译器通常会维护 ...
- hash-1.hash表和hash算法
1.hash表 哈希表,也叫散列表,是根据关键码(Key)而直接访问的数据结构,也就是它把Key映射到表中一个位置来访问记录,即,把key计算成hashcode,把hashcode存到表中.这个把ke ...
- Hash表算法
出处:http://blog.csdn.net/v_JULY_v 第一部分:Top K 算法详解问题描述百度面试题: 搜索引擎会通过日志文件把用户每次检索使用的所有检索串都记录下来,每个查询串的 ...
- HDU 5183 Negative and Positive (NP) ——(后缀和+手写hash表)
根据奇偶开两个hash表来记录后缀和.注意set会被卡,要手写hash表. 具体见代码: #include <stdio.h> #include <algorithm> #in ...
- STL之map应用 +hash表(51nod 1095)
题目:Anigram单词 题意:给出词典,再给出一些单词,求单词的Anigram数量. 思路:先将字串转换成哈希表,然后再用map链接. hash表构造方法汇总:http://www.cnblogs. ...
- 深入了解STL中set与hash_set,hash表基础
一,set和hash_set简介 在STL中,set是以红黑树(RB-Tree)作为底层数据结构的,hash_set是以哈希表(Hash table)作为底层数据结构的.set可以在时间复杂度为O(l ...
- 【转载】一步一步写算法(之hash表)
转载自:http://blog.csdn.net/feixiaoxing/article/details/6885657 [ 声明:版权所有,欢迎转载,请勿用于商业用途. 联系信箱:feixiaox ...
- HASH表原理(装)
HASH表原理 大家都知道,在所有的线性数据结构中,数组的定位速度最快,因为它可通过数组下标直接定位到相应的数组空间,就不需要一个个查找.而哈希表就是利用数组这个能够快速定位数据的结构解决以上的问题的 ...
随机推荐
- Python-PyQt安装
Windows下安装PyQt需要使用 mingw32-make工具, 以在windows下make
- duplicate symbols 错误解决方案
duplicate symbols for architecture arm64 after xCode 8.0 update 升级xcode 8以后提示有的变量重复了,只要在 Build setti ...
- 通过windows自带的系统监视器来查看IIS并发连接数(perfmon.msc)
如果要查看IIS连接数,最简单方便的方法是通过“网站统计”来查看,“网站统计”的当前在线人数可以认为是当前IIS连接数.然而,“网站统计”的当前在线人数统计时间较长,一般为10分钟或15分钟,再加上统 ...
- ReferenceError: Promise is not define
尽管加入了babel-polyfill ,依然出现 [ReferenceError: Promise is not define]的问题.目前只在三星.金立手机出现这种问题.没办法,只能强行修复了. ...
- Atitit.播放系统规划新版本 and 最近版本回顾 v3 pbf.doc
Atitit.播放系统规划新版本 and 最近版本回顾 v3 pbf.doc 1 版本11 (ing)4 1.1 规划h5本地缓存系列 4 1.2 Android版本app4 1.3 双类别系统, ...
- 红茶一杯话Binder (传输机制篇_中)
红茶一杯话Binder (传输机制篇_中) 侯 亮 1 谈谈底层IPC机制吧 在上一篇文章的最后,我们说到BpBinder将数据发到了Binder驱动.然而在驱动层,这部分数据又是如何传递到BBind ...
- Angularjs学习笔记10_directive3
1. restrict M 使用模板 A 属性扩展 2. template,templateUrl,$templateCache 模板缓存 //注射器加载完所有模块时,此方法执行一 ...
- FromHBITMAP 这个函数会丢失透明信息。
在用 FromHBITMAP 你会发现出来的图是带有黑边的,这是因为这个函数有个 bug,解决的办法是用下列的函数进行转换,大体意思就是自己 memcpy 不要用 FromHBITMAP 函数. Bi ...
- vue 组件1
注意:vue组件中的data必须为一个函数,要不vue就会停止工作. 构成组件 组件意味着协同工作,通常父子组件会是这样的关系:组件A在它的模板中使用了组件B,他们之间必然需要相互通信:父组件需要给子 ...
- sqrt函数实现(神奇的算法)
我们平时经常会有一些数据运算的操作,需要调用sqrt,exp,abs等函数,那么时候你有没有想过:这个些函数系统是如何实现的?就拿最常用的sqrt函数来说吧,系统怎么来实现这个经常调用的函数呢? 虽然 ...