原文: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++实现(转)的更多相关文章

  1. hash表长度优化证明

    hash表冲突的解决方法一般有两个方向: 一个是倾向于空间换时间,使用向量加链表可以最大程度的在节省空间的前提下解决冲突. 另外一个倾向于时间换空间,下面是关于这种思路的一种合适表长度的证明过程: 这 ...

  2. 6.数组和Hash表

    当显示多条结果时,存储在变量中非常智能,变量类型会自动转换为一个数组. 在下面的例子中,使用GetType()可以看到$a变量已经不是我们常见的string或int类型,而是Object类型,使用-i ...

  3. PHP数组/Hash表的实现/操作、PHP变量内核实现、PHP常量内核实现 - [ PHP内核学习 ]

    catalogue . PHP Hash表 . PHP数组定义 . PHP变量实现 . PHP常量实现 1. PHP Hash表 0x1: 基本概念 哈希表在实践中使用的非常广泛,例如编译器通常会维护 ...

  4. hash-1.hash表和hash算法

    1.hash表 哈希表,也叫散列表,是根据关键码(Key)而直接访问的数据结构,也就是它把Key映射到表中一个位置来访问记录,即,把key计算成hashcode,把hashcode存到表中.这个把ke ...

  5. Hash表算法

    出处:http://blog.csdn.net/v_JULY_v 第一部分:Top K 算法详解问题描述百度面试题:    搜索引擎会通过日志文件把用户每次检索使用的所有检索串都记录下来,每个查询串的 ...

  6. HDU 5183 Negative and Positive (NP) ——(后缀和+手写hash表)

    根据奇偶开两个hash表来记录后缀和.注意set会被卡,要手写hash表. 具体见代码: #include <stdio.h> #include <algorithm> #in ...

  7. STL之map应用 +hash表(51nod 1095)

    题目:Anigram单词 题意:给出词典,再给出一些单词,求单词的Anigram数量. 思路:先将字串转换成哈希表,然后再用map链接. hash表构造方法汇总:http://www.cnblogs. ...

  8. 深入了解STL中set与hash_set,hash表基础

    一,set和hash_set简介 在STL中,set是以红黑树(RB-Tree)作为底层数据结构的,hash_set是以哈希表(Hash table)作为底层数据结构的.set可以在时间复杂度为O(l ...

  9. 【转载】一步一步写算法(之hash表)

    转载自:http://blog.csdn.net/feixiaoxing/article/details/6885657 [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaox ...

  10. HASH表原理(装)

    HASH表原理 大家都知道,在所有的线性数据结构中,数组的定位速度最快,因为它可通过数组下标直接定位到相应的数组空间,就不需要一个个查找.而哈希表就是利用数组这个能够快速定位数据的结构解决以上的问题的 ...

随机推荐

  1. list操作总结. dict操作及文件操作

    1: 列表的操作 help(list) # 列表的帮助,列出所有列表的用法 type(name) # type判断数据类型是列表还是字典或者元组 isinstance("字符", ...

  2. Filter介绍,运行顺序,实例

    Filter介绍 Filter可觉得是Servlet的一种"变种",它主要用于对用户请求进行预处理,也能够对HttpServletResponse进行后处理,是个典型的处理链. 它 ...

  3. sublime text 3 设置默认自动换行

    如果每次打开文件都不自动换行, 设置如下在sublime菜单栏选择 "选项-->设置-用户", 在打开的配置文件中添加 "word_wrap" : fal ...

  4. Yum Error Another app is currently holding the yum lock; waiting for it to exit

    Another app is currently holding the yum lock; waiting for it to exit... The other application is: P ...

  5. 下载The Swift Programming Language.mobi版

    下载 The Swift Programming Language.mobi 下载 http://download.csdn.net/detail/swifttrain/7444501

  6. 使用SVN管理unityproject

     我们的项目使用SVN管理.这几天遇到了几个问题,攻克了一下.顺便做了一个总结. 1.关于使用SVN管理unity项目的一些设置和说明 首先在unity中进行两部操作:Edit->Proje ...

  7. 关于extern的说明

    extern的作用: extern可置于变量或者函数前,以表示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义.   声明外部变量 现代编译器一般采用按文件编译的方式 ...

  8. mock实例方法

    1.Mockito.when(categoryService.queryTopCategory("1")).thenReturn(categories);//返回的是list列表, ...

  9. [原创]超强C#图片上传,加水印,自动生成缩略图源代码

    <%@ Page Language=“C#“ AutoEventWireup=“true“ %> <%@ Import Namespace=“System“ %> <%@ ...

  10. active mq 配置

    <transportConnectors> <!-- DOS protection, limit concurrent connections to 1000 and frame s ...