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表原理 大家都知道,在所有的线性数据结构中,数组的定位速度最快,因为它可通过数组下标直接定位到相应的数组空间,就不需要一个个查找.而哈希表就是利用数组这个能够快速定位数据的结构解决以上的问题的 ...
随机推荐
- RabbitMQ快速入门python教程
摘要:HelloWorld 简介 RabbitMQ:接受消息再传递消息,可以视为一个“邮局”.发送者和接受者通过队列来进行交互,队列的大小可以视为无限的,多个发送者可以发生给一个队列,多个接收者也可以 ...
- 信号处理的好书Digital Signal Processing - A Practical Guide for Engineers and Scientists
诚心给大家推荐一本讲信号处理的好书<Digital Signal Processing - A Practical Guide for Engineers and Scientists>[ ...
- android studio - 隐藏编辑器标签块上面的索引
- javascript (function() { /* code */ })() 自执行函数
(function(){ function a(){ alert("a"); } })(); 自执行匿名函数: 常见格式:(function() { /* code */ })() ...
- c++ 请抛弃匈牙利命名法 - 变量命名代码风格的建议。
我只针对c++码农们讲,其他语言不了解不过应该大同小异.曾几何时翻开21天学通c++系列等脑残入门书,都以匈牙利命名法示人(DWORD dwXXX, int nXXX, string strXXX). ...
- html 标签 链接
<a href="http://www.baidu.com">百度</a> <a href="#here">here< ...
- GitBlit (1)-- 在linux 安装 GitBlit 并运行
Git是一款注重速度.数据完整性.分布式支持和非线性工作流的分布式版本控制工具.Git最初由Linus Torvalds在2005年为Linux内核开发而设计,如今已经成为被广泛接受的版本控制系统. ...
- 使用transform实现手风琴布局
- Easyui 基于kindeditor的扩展
源码 /** * Author : ____′↘夏悸 * Easyui KindEditor的简单扩展. * 有了这个之后,你就可以像使用Easyui组件的方式使用KindEditor了 * 前提是你 ...
- HTML CSS表格如何控制上下间距
css:td{margin-top:10px; 上间距margin-right:10px; 右间距margin-bottom:10px; 下间距margin-left:10px; 左间距}