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表原理 大家都知道,在所有的线性数据结构中,数组的定位速度最快,因为它可通过数组下标直接定位到相应的数组空间,就不需要一个个查找.而哈希表就是利用数组这个能够快速定位数据的结构解决以上的问题的 ...
随机推荐
- 灰色预测--matlab&python实现
function SGrey X0 = input('请输入原始负荷数据:'); %输入原始数据 n = length(X0); %原始n年数据 %累加生成 X1 = zeros(1,n); for ...
- centos7安装thrift
1. 升级所有软件包 yum -y update 2.安装开发工具 yum -y groupinstall "Development Tools" 3.安装wget yum -y ...
- Atitit.eclipse comment template注释模板
Atitit.eclipse comment template注释模板 1. Code templet1 1.1. Settpath1 1.2. 设置存储1 1.3. 导出设置1 2. Java d ...
- Atitit.通过null 参数 反射 动态反推方法调用
Atitit.通过null 参数 反射 动态反推方法调用 此时,直接使用java apache的ref工具都失效了.必须要自己实现了. 如果调用接口方法的话,就不能使用apache的ref工具,可 ...
- 在modelsim中加入quartus仿真库
找到modelsim安装目录下的modelsim.ini文件. 将modelsim.ini的只读属性去掉. 打开quartus软件.选择Launch Simulation Library Compil ...
- 网页webbrowser
http://www.codeproject.com/Articles/50544/Using-the-WebBrowser-Control-in-ASP-NET/
- IOS MagicRecord 详解 (转载)
2014-10-22 14:37 6137人阅读 评论(6) 收藏 举报 IOSMagicRecordCoreData 目录(?)[+] 刚开始接触IOS不久,尝试着翻译一些博客,积累技术,与大家共享 ...
- ubuntu如何使用minicom
minicom是linux下串口通信的软件,它的使用完全依靠键盘的操作,虽然没有“超级终端”那么易用,但是使用习惯之后读者将会体会到它的高效与便利,下面将讲解minicom的安装和配置. 一.安装mi ...
- js或jquery实现页面打印(局部打印)
首先定义css样式: 复制代码代码如下: @media print { .noprint { display: none;color:green } } 对于不想打印的内容只用在标签中加上 cla ...
- fabric 自动化部署
fabric 项目发布和运维的工作相当机械,频率还蛮高,导致时间浪费在敲大量重复的命令上. 修复bug什么的,测试,提交版本库(2分钟),ssh到测试环境pull部署(2分钟),rsync到线上机器A ...