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表原理 大家都知道,在所有的线性数据结构中,数组的定位速度最快,因为它可通过数组下标直接定位到相应的数组空间,就不需要一个个查找.而哈希表就是利用数组这个能够快速定位数据的结构解决以上的问题的 ...
随机推荐
- web本地存储localStorage和sessionStorage
用谷歌浏览器调试网页程序时候发现有一个这个栏目 记录本地存储的相关信息(cookie,sessionStorage,LocalStorage等)的存储信息 1.LocalStorage localst ...
- URAL 1750 Pakhom and the Gully 计算几何+floyd
题目链接:点击打开链接 gg.. . #pragma comment(linker, "/STACK:1024000000,1024000000") #include <cs ...
- SPOJ QTREE3 lct
题目链接 题意: 给定n个点 q个询问 以下n-1行给出树边,点有黑或白色.初始化为白色 以下q行: 询问有2种: 1. 0 x 把x点黑变白,白变黑 2.1 x 询问Path(1,x)路径上第一个黑 ...
- 用brew安装gcc48
由于mac自带的gcc的版本过低,因此想自己装一个新的gcc. 在网上搜索了一圈后发现用brew install安装比较简单,但可能由于本地的brew有冲突,因此网上的攻略都没有效果. 通过在gith ...
- shell脚本之练习题
设计一个shell程序,添加一个新组为class1,然后添加属于这个组的30个用户,用户名的形式为stdxx,其中xx从01到30. i=1 groupadd class1 while [ $i -l ...
- (Nhibernate )XML配置文件的智能感知(IntelliSense)功能
XML配置文件的智能感知(IntelliSense)功能 在使用一些第三方的程序库(Nhibernate,Ibatis...)常常需要手工编写比较复杂的配置文件,如果没有像VS IDE那样的Int ...
- UI-2-UILabel&UIImageView-补充
课程要点: 控件之间的继承关系. UILabel UIImageView 利用UIImageView实现帧动画 补充 试图之间的继承关系 昨天学习UIView的时候,了解到UIView里面有以下几个常 ...
- springMVC集成 -- shiro(配置)
备注:文中配置基本来自尚硅谷视频教程,也可自行参照shiro官方教程:http://shiro.apache.org/spring.html 1.首先通过maven导入shiro相关依赖jar包,修改 ...
- 着手打造你的随身系统---将linux装进移动硬盘
将Ubuntu等linux系统安装到移动硬盘--操作系统随身携带 前言 刚刚接触ubuntu,听说可以将linux系统安装到移动硬盘上,所以最近一周都在尝试将ubuntu安装到新买的移动 ...
- Linux 常用文件管理命令
Command Description cat filename 查看文件内容.举例:cat pushticketfast.sh --最好用tail -n 500 cd dirname 改变所在 ...