数据结构实验四哈希表及其查找
哈希表(Hash)的查找

哈希表(Hash)的查找一、哈希表相关概念1、哈希函数的基本概念哈希表又称散列表。
哈希表存储的基本思想是:以数据表中的每个记录的关键字 k为自变量,通过一种函数H(k)计算出函数值。
把这个值解释为一块连续存储空间(即数组空间)的单元地址(即下标),将该记录存储到这个单元中。
在此称该函数H为哈希函数或散列函数。
按这种方法建立的表称为哈希表或散列表。
理想情况下,哈希函数在关键字和地址之间建立了一个一一对应关系,从而使得查找只需一次计算即可完成。
由于关键字值的某种随机性,使得这种一一对应关系难以发现或构造。
因而可能会出现不同的关键字对应一个存储地址。
即k1≠k2,但H(k1)=H(k2),这种现象称为冲突。
把这种具有不同关键字值而具有相同哈希地址的对象称“同义词”。
在大多数情况下,冲突是不能完全避免的。
这是因为所有可能的关键字的集合可能比较大,而对应的地址数则可能比较少。
对于哈希技术,主要研究两个问题:(1)如何设计哈希函数以使冲突尽可能少地发生。
(2)发生冲突后如何解决。
2、哈希函数的构造方法常见的构造方法有很多种,如直接定址法,数字分析法,平方取中法等。
接下来,我们介绍其中的几种:(1)除留余数法取关键字k被某个不大于表长m的数p除后所得余数作为哈希函数地址的方法。
即:H(k)=k mod p这种方法的关键是选择好p。
使得数据集合中的每一个关键字通过该函数转化后映射到哈希表的任意地址上的概率相等。
理论研究表明,一般取p为小于m的最大质数或不包含小于20的质因素的合数。
(2)平方取中法先将关键字平方,然后取其中间几位作为散列地址。
所取位数由地址空间范围决定。
若地址空间小于所取位数值决定的范围,可通过乘以一比例因子来解决。
(3)折叠法把关键字分割成位数相等(最后一部分的位数可以不同)的几部分,然后通过折叠后将几部分进行相加,丢掉进位位,所得值即为散列地址。
散列的位数由地址空间的位数而定。
分割方法:从右至左相加方法有两种:移位叠加:将分割后的各部分低位对齐相加。
详解哈希表的查找

详解哈希表的查找哈希表和哈希函数在记录的存储位置和它的关键字之间是建立一个确定的对应关系(映射函数),使每个关键字和一个存储位置能唯一对应。
这个映射函数称为哈希函数,根据这个原则建立的表称为哈希表(Hash Table),也叫散列表。
以上描述,如果通过数学形式来描述就是:若查找关键字为key,则其值存放在f(key) 的存储位置上。
由此,不需比较便可直接取得所查记录。
注:哈希查找与线性表查找和树表查找最大的区别在于,不用数值比较。
冲突若key1 ≠ key2 ,而f(key1) = f(key2),这种情况称为冲突(Collision)。
根据哈希函数f(key)和处理冲突的方法将一组关键字映射到一个有限的连续的地址集(区间)上,并以关键字在地址集中的“像”作为记录在表中的存储位置,这一映射过程称为构造哈希表。
构造哈希表这个场景就像汽车找停车位,如果车位被人占了,只能找空的地方停。
构造哈希表由以上内容可知,哈希查找本身其实不费吹灰之力,问题的关键在于如何构造哈希表和处理冲突。
常见的构造哈希表的方法有 5 种:(1)直接定址法说白了,就是小学时学过的一元一次方程。
即 f(key) = a * key + b。
其中,a和b 是常数。
(2)数字分析法假设关键字是R进制数(如十进制)。
并且哈希表中可能出现的关键字都是事先知道的,则可选取关键字的若干数位组成哈希地址。
选取的原则是使得到的哈希地址尽量避免冲突,即所选数位上的数字尽可能是随机的。
(3)平方取中法取关键字平方后的中间几位为哈希地址。
通常在选定哈希函数时不一定能知道关键字的全部情况,仅取其中的几位为地址不一定合适;而一个数平方后的中间几位数和数的每一位都相关,由此得到的哈希地址随机性更大。
取的位数由表长决定。
(4)除留余数法取关键字被某个不大于哈希表表长 m 的数 p 除后所得的余数为哈希地址。
即f(key) = key % p (p ≤ m)这是一种最简单、最常用的方法,它不仅可以对关键字直接取模,也可在折叠、平方取中等运算之后取模。
哈希表的定义查找及分析bklt

一、直接地址法
:
取关键字或关键字的某个线性函值为哈希地址
即: H(key) = key 或: H(key) = a* key + b
其中,a, b为常数。
二、数字分析法
假设关键字集合中的每个关键字都是由 s 位 数字组成 (u1, u2, …, us),分析关键字集中的全 体, 并从中提取分布均匀的若干位或它们的组 合作为地址。
查找不成功时的ASL
ASLunsucc=( )/11
= /11
10
11
3
8
线性探测再散列的优点:
只要哈希表未满,总能找到一个空地址。
缺点:会产生二次聚集。
01…
70 19 33 18
5678 9
… 12
9
二、 链地址法
在哈希表的每一个单元中存放一个指针,将所 有的同义词连成一个链表。 假设哈希地址在区间[0 .. m-1]上,则哈希表为
一个指针数组。
typedef struct node{ //定义链表中结点 KeyType key; 其它成员 ; struct node *next;
} Node,*Nodeptr; typedef Nodeptr chainhash[m];// 定义指针数组10
例1: 关键字集合 { 19, 01, 23, 14, 55, 68, 11, 82, 36 }
若采用线性探测再散列处理冲突
0 1 2 3 4 5 6 7 8 9 10
55 01 23 14 68 11 82 36 19
11 21 3 62 5 1
若采用二次探测再散列处理冲突
0 1 2 3 4 5 6 7 8 9 10
哈希实验报告

引言概述:本文旨在对哈希实验进行报告,重点介绍哈希实验的二次探测法、哈希函数、哈希表的查找、插入与删除操作,并分析实验结果。
通过本实验的开展,我们对哈希算法的原理、实现和性能有了更深入的理解,也增加了对数据结构的实践能力。
正文内容:一、二次探测法1.定义与原理2.步骤与流程3.优缺点分析4.实验过程与结果5.实验中的注意事项二、哈希函数1.哈希函数的设计原则2.常见的哈希函数算法3.哈希冲突与解决方法4.哈希函数的优化策略5.实验中的哈希函数选择与应用三、哈希表的查找操作1.哈希表的存储结构与基本操作2.直接定址法查找3.拉链法查找4.其他查找方法与比较5.实验结果与分析四、哈希表的插入与删除操作1.插入操作的实现思路2.插入操作的效率分析3.删除操作的实现思路4.删除操作的效率分析5.实验结果分析与对比五、实验结果与总结1.实验数据的统计与分析2.实验中的问题与解决方案3.实验结论与总结4.对哈希算法的进一步探讨与应用展望5.实验的意义与启示总结:通过对哈希实验的详细阐述,我们对二次探测法、哈希函数、哈希表的查找、插入与删除操作有了更深入的了解。
实验结果与分析表明,在哈希表的实现中,选择合适的哈希函数、解决哈希冲突以及优化插入与删除操作,对提高哈希表的性能至关重要。
哈希算法作为一种重要的数据结构应用,具有广泛的应用前景,在实际问题中具有重要的实践意义。
通过本次实验,我们不仅提升了对数据结构的理论理解,也增强了数据结构算法的实践能力,为今后的学习与研究打下了坚实的基础。
数据结构哈希表的实验报告

课程实习报告一、需求分析:1.本程序来自于图书馆靠书名来检索想要查找的书问题。
2.本程序要求:(1)根据输入建立图书名称表,采用创建散列表实现。
(2)建散列表后,如果想要查找的数据在散列表中输出yes否则输出no。
二、哈希表简介结构中存在关键字和K相等的记录,则必定存储在f(K)的位置上。
由此,不需比较便可直接取得所查记录。
这个对应关系f称为散列函数(Hash function),按这个思想建立的表为散列表。
* 对不同的关键字可能得到同一散列地址,即key1≠key2,而f(key1)=f(key2),这种现象称冲突。
具有相同函数值的关键字对该散列函数来说称做同义词。
* 综上所述,根据散列函数H(key)和处理冲突的方法将一组关键字映象到一个有限的连续的地址集(区间)上,并以关键字在地址集中的“象”,作为这条记录在表中的存储位置,这种表便称为散列表,这一映象过程称为散列造表或散列,所得的存储位置称散列地址。
这个现象也叫散列桶,在散列桶中,只能通过顺序的方式来查找,一般只需要查找三次就可以找到。
科学家计算过,当负载因子(load factor)不超过75%,查找效率最高。
* 若对于关键字集合中的任一个关键字,经散列函数映象到地址集合中任何一个地址的概率是相等的,则称此类散列函数为均匀散列函数(Uniform Hash function),这就是使关键字经过散列函数得到一个“随机的地址”,从而减少冲突。
程序设计流程程序思想(一)哈希函数unsigned int hash_BKDE(char *str)生成映射地址,成为散列表的编号。
(二)哈希表HashTable::HashTable()通过数组储存元素(三)插入函数void HashTable::insert(char*c)插入字符串,先计算要插入字符串生成的映射地址,然后在相应的地址插入,如果没有空位查找空位插入。
(四)查找函数bool HashTable::find(char*c)进行查找,先计算要生成字符串的地址,再到散列表中进行查找比较。
数据结构查找算法实验报告

数据结构实验报告实验第四章:实验:简单查找算法一.需求与规格说明:查找算法这里主要使用了顺序查找,折半查找,二叉排序树查找与哈希表查找四种方法。
由于自己能力有限,本想实现其她算法,但没有实现.其中顺序查找相对比较简单,折半查找参考了书上得算法,二叉排序树查找由于有之前做二叉树得经验,因此实现得较为顺利,哈希表感觉做得并不成功,感觉还就是应该可以进一步完善,应该说还有很大得改进余地。
二.设计思想:开始得时候提示输入一组数据。
并存入一维数组中,接下来调用一系列查找算法对其进行处理。
顺序查找只就是从头到尾进行遍历。
二分查找则就是先对数据进行排序,然后利用三个标志,分别指向最大,中间与最小数据,接下来根据待查找数据与中间数据得比较不断移动标志,直至找到。
二叉排序树则就是先构造,构造部分花费最多得精力,比根节点数据大得结点放入根节点得右子树,比根节点数据小得放入根节点得左子树,其实完全可以利用递归实现,这里使用得循环来实现得,感觉这里可以尝试用递归.当二叉树建好后,中序遍历序列即为由小到大得有序序列,查找次数不会超过二叉树得深度。
这里还使用了广义表输出二叉树,以使得更直观。
哈希表则就是利用给定得函数式建立索引,方便查找.三.设计表示:四.实现注释:其实查找排序这部分与前面得一些知识联系得比较紧密,例如顺序表得建立与实现,顺序表节点得排序,二叉树得生成与遍历,这里主要就是中序遍历.应该说有些知识点较为熟悉,但在实现得时候并不就是那么顺利。
在查找到数据得时候要想办法输出查找过程得相关信息,并统计。
这里顺序查找与折半查找均使用了数组存储得顺序表,而二叉树则就是采用了链表存储得树形结构。
为了直观起见,在用户输入了数据后,分别输出已经生成得数组与树。
折半查找由于只能查找有序表,因此在查找前先调用函数对数据进行了排序。
在查找后对查找数据进行了统计.二叉排序树应该说由于有了之前二叉树得基础,并没有费太大力气,主要就是在构造二叉树得时候,要对新加入得节点数据与跟数据进行比较,如果比根节点数据大则放在右子树里,如果比根节点数据小则放入左子树。
哈希表实验报告

数据结构实验报告四——哈希表查找名字(字符串)实验题目:哈希表查找名字(字符串)实验目标:输入一组名字(至少50个),将其保存并利用哈希表查找。
输出哈希查找冲突次数,哈希表负载因子、查找命中率。
数据结构:哈希表和数组(二维)。
二维数组用于静态顺序存储名字(字符串),哈希表采用开放定址法,用于存储名字(字符串)对应的关键字并实现对名字(字符串)的查找。
需要的操作有:1.关键字求取(主函数中两次出现,未单独编为函数)关键字key=abs(字符串首位ASCII码值-第二位ASCII码值+第([]+1)位ASCII码值-最后一位ASCII码值-倒数第二位ASCII码值)*字符串长度(abs为求整数绝对值的函数)。
2.处理关键字的哈希函数(Hash)利用平方取中法求关键值key在哈希表中的位置。
公式add=(key*key)%1000/LENGTH(add 为key在哈希表中的地址)。
int Hash(int key){return((key*key)/1000%LENGTH);}3.处理哈希表中冲突的函数(Collision)利用线性探测再散列处理冲突,利用全局变量count统计冲突次数。
int Collision(int key,int Hashtable[]){int i;for(i=1;i<=LENGTH;i++){if(Hashtable[(Hash(key)+i)%LENGTH]==-1)return((Hash(key)+i)%LENGTH);count++;}}4.哈希表初始化(InitHash)void InitHash(int Hashtable[]){int i;for(i=0;i<LENGTH;i++)Hashtable[i]=-1;}5.向哈希表中插入关键字(InsertHash)void InsertHash(int key,int Hashtable[]){int add;if(Hashtable[add]==-1)Hashtable[add]=key;else{add=Collision(key,Hashtable);Hashtable[add]=key;}}6.查找关键字在哈希表中的存储位置(SearchHash)int SearchHash(int key,int Hashtable[]){int add;add=Hash(key);if(Hashtable[add]==key)return add;while(Hashtable[add]!=key&&Hashtable[add]!=-1)add=Collision(key,Hashtable);return add;}7.输出哈希表(PrintHash)(帮助调试用)void PrintHash(int Hashtable[]){int i;for(i=0;i<LENGTH;i++)if(Hashtable[i]!=-1)printf("%3d:%d\n",i+1,Hashtable[i]);}8.求字符串长度(strlen)(函数库<string.h>包含)以及求整数的绝对值(abs)(函数库<math.h>包含)算法设计:1建立长度为LENGTH的哈希表Hash(LENGTH具体值由宏定义决定)。
数据结构设计报告--哈希查找与实现

数据结构课程设计报告书班级BX1001专业计算机科学与技术学号101003020139姓名赵冠博课题描述:哈希表的查找与实现分析1、 需求分析:本次课程设计需要实现哈希表的建立和查找,具体内容如下:建立哈希函数,从而根据用户输入的数据元素个数和各元素的值建立哈希表,即数据的添加和存储。
如果输入的元素个数超出规定范围,则打印出错信息,并提示重新输入信息。
哈希表建立好之后,用户可以输入想要查找的值,屏幕显示相应信息。
如果存在此值,屏幕显示该值信息;如果不存在,则显示该值不存在;如果想退出系统,则按提示输入命令。
2、 总体结构设计:1> 一个哈希表结构hashtable ,2>一个main ()主函数(完成数据输入和函数调用)、3>五个功能函数:Initialhash ()//初始化哈希表Printhash ()//输出哈希表的所有元素及其位置Searchhash ()//查找哈希表inserthash ()//查找哈希表deletehash ()//查找哈希表3、 各子模块设计:构成如下图所示:【设计思想】选取某个函数,依该函数按关键字计算元素的存储位置,并按此存放;查找时,由同一个函数对给定值kx 计算地址,将kx 与地址单元中元素关键字进行比较,确定查找是否成功,这就是哈希方法。
哈希方法中使用的转换函数称为Searchhash () Printhash () Initalhash() inserthash () deletehash哈希查找程序main()哈希函数。
程序首先通过插入操作建立哈希表,接着显示数据,然后运用哈希查找找到数据,如没有找到则显示查找错误,找到则显示查找成功。
4、编程实现:【实验程序主要代码】:#define MAXSIZE 12 //哈希表的最大容量,与所采用的哈希函数有关enum BOOL{False,True};enum HAVEORNOT{NULLKEY,HAVEKEY,DELKEY};//哈希表元素的三种状态,没有记录、有记录、有过记录但已被删除typedef struct //定义哈希表的结构{ int elem[MAXSIZE]; //数据元素体HAVEORNOT elemflag[MAXSIZE];//元素状态,没有记录、有记录、有过记录但已被删除 int count; // 哈希表中当前元素的个数}HashTable;typedef struct{ int keynum; // 记录的数据域,只有关键字一项}Record;void InitialHash(HashTable&); // 初始化哈希表void PrintHash(HashTable); // 显示哈希表中的所有元素BOOL SearchHash(HashTable,int,int&); // 在哈希表中查找元素BOOL InsertHash(HashTable&,Record); // 在哈希表中插入元素BOOL DeleteHash(HashTable&,Record); // 在哈希表中删除元素int Hash(int); // 哈希函数void main(){ HashTable H; // 声明哈希表Hchar ch,j='y';int position,n,k;Record R;BOOL temp;InitialHash(H);while(j!='n'){ printf("\n\t 哈希查找 ");printf("\n\t**************************************");printf("\n\t* 1-----建表 *");printf("\n\t* 2-----显示 *");printf("\n\t* 3-----查找 *");printf("\n\t* 4-----插入 *");printf("\n\t* 5-----删除 *");printf("\n\t* 0-----退出 *");printf("\n\t**************************************");printf("\n\n\t请输入菜单号:");scanf(" %c",&ch); // 输入操作选项switch(ch){ case '1':printf("\n请输入元素个数(<10): ");scanf("%d",&n);printf("\n");for( k=0;k<n;k++){ printf("请输入第%3d个整数: ",k+1);scanf("%d",&R.keynum); // 输入要插入的记录temp=InsertHash(H,R);};break;case '2':if(H.count) PrintHash(H); // 哈希表不空else printf("\n散列表为空表!\n");break;case '3':if(!H.count) printf("\n散列表为空表!\n"); // 哈希表空else{ printf("\n请你输入要查找元素(int) :");scanf("%d",&R.keynum); // 输入待查记录的关键字temp=SearchHash(H,R.keynum,position);// temp=True:记录查找成功;temp=False:没有找到待查记录if(temp) printf("\n查找成功该元素位置是 %d\n",position); else printf("\n本散列表没有该元素!\n");}break;case '4':if(H.count==MAXSIZE) // 哈希表已满 { printf("\n散列表已经满!\n");break; }printf("\n请输入要插入元素(int):");scanf("%d",&R.keynum); // 输入要插入的记录 temp=InsertHash(H,R);// temp=True:记录插入成功;temp=False:已存在关键字相同的记录if(temp) printf("\n元素插入成功!\n");else printf("\n元素插入失败,相同元素本散列表已经存在!\n"); break;case '5':printf("\n请你输入要删除元素(int):");scanf("%d",&R.keynum); // 输入要删除记录的关键字temp=DeleteHash(H,R);// temp=True:记录删除成功;temp=False:待删记录不存在if(temp) printf("\n删除成功!\n");else printf("\n删除元素不在散列表中!\n");break;default: j='n';}}printf("\n\t欢迎再次使用本程序,再见!\n");}void InitialHash(HashTable &H) // 哈希表初始化{ int i;H.count=0;for(i=0;i<MAXSIZE;i++) H.elemflag[i]=NULLKEY;}void PrintHash(HashTable H) // 显示哈希表所有元素及其所在位置{ int i;for(i=0;i<MAXSIZE;i++) printf("%-4d",i); // 显示哈希表中记录所在位置printf("\n");for(i=0;i<MAXSIZE;i++) // 显示哈希表中记录值if(H.elemflag[i]==HAVEKEY) printf("%-4d",H.elem[i]);else printf("%4c",' ');printf("\ncount:%d\n",H.count); // 显示哈希表当前记录数}BOOL SearchHash(HashTable H,int k,int &p){ // 在开放定址哈希表H中查找关键字为k的数据元素,若查找成功,以p指示待查//数据元素在表中的位置,并返回True;否则,以p指示插入位置,并返回Falseint p1;p1=p=Hash(k); // 求得哈希地址while(H.elemflag[p]==HAVEKEY&&k!=H.elem[p]) //该位置填有记录并且关键字不相等 { p++; // 冲突处理方法:线性探测再散列if(p>=MAXSIZE) p=p%MAXSIZE; // 循环搜索if(p==p1) return False; // 整个表已搜索完,没有找到待查元素 }if(k==H.elem[p]&&H.elemflag[p]==HAVEKEY) // 查找成功,p指示待查元素位置 return True;else return False; // 查找不成功}BOOL InsertHash(HashTable &H,Record e){ // 查找不成功时插入元素e到开放定址哈希表H中,并返回True,否则返回False int p;if(SearchHash(H,e.keynum,p)) // 表中已有与e有相同关键字的元素return False;else{ H.elemflag[p]=HAVEKEY; // 设置标志为HAVEKEY,表示该位置已有记录H.elem[p]=e.keynum; // 插入记录H.count++; // 哈希表当前长度加一return True;}}BOOL DeleteHash(HashTable &H,Record e){ // 在查找成功时删除待删元素e,并返回True,否则返回Falseint p;if(!SearchHash(H,e.keynum,p)) return False; // 表中不存在待删元素else{ H.elemflag[p]=DELKEY; // 设置标志为DELKEY,表明该元素已被删除 H.count--; // 哈希表当前长度减一return True;}}int Hash(int kn){ return (kn%11); } // 哈希函数:H(key)=key MOD 115、测试结果:【程序运行结果】建表和显示:查找:插入:删除:通过分析输入数据和运行结果,证明程序顺利完成实验内容和要求。
哈希表的实验报告

哈希表的实验报告哈希表的实验报告哈希表是一种常见的数据结构,用于存储和查找数据。
在本次实验中,我们将探索哈希表的原理、实现和性能,并通过实验验证其效果。
一、实验目的本次实验的目的是探索哈希表的原理和实现方法,并通过实验测试不同哈希函数和哈希表大小对性能的影响。
二、实验原理哈希表是一种基于哈希函数的数据结构,它将数据存储在数组中,通过哈希函数将数据映射到数组的特定位置。
哈希函数将数据转换为数组的索引,使得数据可以快速存储和查找。
哈希函数的选择很重要,一个好的哈希函数应该具备以下特点:1. 均匀性:哈希函数应该将数据均匀地分布到不同的索引位置,以避免冲突。
2. 高效性:哈希函数应该具有高效的计算速度,以提高哈希表的性能。
3. 低冲突:哈希函数应该尽可能减少冲突的发生,以提高哈希表的查找效率。
三、实验方法1. 实现哈希表:我们首先需要实现一个基本的哈希表数据结构。
哈希表可以使用数组来存储数据,每个数组元素称为一个桶,每个桶可以存储多个数据项。
在实现哈希表时,我们需要考虑如何处理冲突,常见的方法有链地址法和开放地址法。
2. 实现哈希函数:我们需要实现不同的哈希函数,以测试它们的性能。
常见的哈希函数包括除余法、乘法和平方取中法等。
我们可以通过实验比较它们的性能,选择最合适的哈希函数。
3. 测试性能:我们需要设计一系列实验,测试不同哈希函数和哈希表大小对性能的影响。
可以通过插入、查找和删除等操作来评估哈希表的性能。
我们可以记录每个操作的平均时间复杂度和空间占用情况,并绘制图表来展示结果。
四、实验结果与分析通过实验,我们得到了不同哈希函数和哈希表大小下的性能数据。
我们可以观察到不同哈希函数对性能的影响,并选择最优的哈希函数。
同时,我们还可以观察到哈希表大小对性能的影响,选择合适的哈希表大小以平衡性能和空间占用。
五、实验总结本次实验我们深入了解了哈希表的原理和实现方法,并通过实验验证了不同哈希函数和哈希表大小对性能的影响。
数据结构.第9章.查找.4.哈希表

§9.3 哈希表
开放地址法
例:关键码集为 {47,7,29,11,16,92,22,8,3}, 设:哈希表表长为m=11; 哈希函数为Hash(key)=key mod 11; 拟用线性探测法处理冲突。建哈希表: 0 1
11 22
2
3
4
5
6
3
7
7
8
29
9
8
10
47 92 16
§9.3 哈希表
开放地址法
选用关键字的某几位组合成哈希地址。
选用原则应当是:各种符号在该位上出现的频率大致
相同。
适于关键字位数比哈希地址位数大,且可能出现的关 键字事先知道的情况。
§9.3 哈希表
数字分析法
例:有一组(例如80个)关键码,其样式如下: 讨论: 3 4 7 0 5 2 4 ① 第1、2位均是“3和4”,第3位也只有 3 4 9 1 4 8 7 3 4 8 2 6 9 6 “ 7、8、9”,因此,这几位不能用,余 3 4 8 5 2 7 0 下四位分布较均匀,可作为哈希地址选用。 3 4 8 6 3 0 5 ② 若哈希地址取两位(因元素仅80个), 3 4 9 8 0 5 8 则可取这四位中的任意两位组合成哈希地 3 4 7 9 6 7 1 址,也可以取其中两位与其它两位叠加求 3 4 7 3 9 1 9 和后,取低两位作哈希地址。 位号:① ② ③ ④ ⑤ ⑥ ⑦
拟用二次探测法处理冲突。建哈希表如下: Hi = ( H(K)+di ) mod m 其中di =12, -12, 22,-22,…, j2, -j2 ( j≤m/2)。
0 1
11 22
2
3
3
4
5
6
7
数据结构查找实验报告

数据结构查找实验报告数据结构查找实验报告一、引言数据结构是计算机科学中的重要概念之一,它涉及到组织和管理数据的方式和方法。
在实际应用中,我们经常需要对大量的数据进行查找操作,因此查找算法的效率和准确性显得尤为重要。
本实验旨在通过对比不同的查找算法,探索其性能和适用场景。
二、实验目的本实验的目的是比较常见的查找算法,包括线性查找、二分查找和哈希查找,分析它们的时间复杂度和空间复杂度,并通过实验数据验证其效率。
三、实验方法1. 实验环境本实验使用C++语言进行编程,选择了Visual Studio作为开发环境,以保证实验结果的准确性和可靠性。
2. 实验步骤(1)线性查找线性查找是最简单直接的查找算法,它的原理是从头到尾逐个比较待查找元素和数组中的元素,直到找到目标元素或遍历完整个数组。
在实验中,我们随机生成一个包含一定数量元素的有序数组,并使用线性查找算法查找目标元素。
(2)二分查找二分查找是一种高效的查找算法,它基于有序数组的特点,通过不断缩小查找范围来快速定位目标元素。
在实验中,我们同样生成一个有序数组,并使用二分查找算法进行查找操作。
(3)哈希查找哈希查找是一种基于哈希表的查找算法,它通过将关键字映射到哈希表中的位置来实现快速查找。
在实验中,我们使用哈希查找算法对一个包含大量元素的数组进行查找。
四、实验结果与分析1. 时间复杂度通过实验数据统计,我们可以得到不同查找算法的平均时间复杂度。
线性查找的时间复杂度为O(n),其中n为数组的大小;二分查找的时间复杂度为O(logn),哈希查找的时间复杂度为O(1)。
可以看出,随着数据规模增大,二分查找和哈希查找的效率明显高于线性查找。
2. 空间复杂度线性查找的空间复杂度为O(1),即不需要额外的存储空间;二分查找的空间复杂度为O(1),哈希查找的空间复杂度为O(n),其中n为哈希表的大小。
因此,从空间复杂度的角度来看,线性查找和二分查找相对较优。
3. 实验结果通过多次实验,我们得到了不同查找算法的平均查找时间。
数据结构实验报告(哈希表)

散列表的设计实验报告1、题目:散列表的设计:针对某个集体中人名设计一个散列表,使得平均查找长度不超过R,并完成相应的建表和查表程序。
2、基本要求:假设人名为中国人姓名的汉语拼音形式。
待填入哈希表的人名共30个,取平均查找长度上限为2,哈希函数用除留余数法构造,用伪随机探测再散列法处理冲突。
人名长度不超过20个字符。
可先对过长的人名作折叠处理。
3、设计思想:a.构造哈希函数的方法很多,常用的有(1)直接定址法(2)数字分析法;(3)平方取中法;(4)折叠法;( 5)除留余数法;(6)随机数法;本实验采用的是除留余数法:取关键字被某个不大于哈希表表长m的数p除后所得余数为哈希地址H(key)=key MOD p,p<=m.b.哈希函数可以减少冲突,但不能避免。
通常用的处理冲突的方法有:(1)开放定址法,这种方法还包含三种形式,一种叫线性探测再散列,一种叫二次探测再散列,另一种叫伪随机探测再散列。
本实验采用的是第三种伪随机探测再散列。
求下一个开放地址的公式为:Hi=(H(k)+di)MOD m (Di=伪随机数序列)c.对哈希表的操作InitNameList() 操作结果:姓名(结构体数组)初始化CreateHashList() 操作结果:建立哈希表FindList() 操作结果:在哈希表中查找Display() 操作结果:显示哈希表4、程序结构图5、流程图6、数据测试7、程序清单#include<iostream>#include<string>using namespace std;#define HASH_LENGTH 50#define M 47#define NAME_NO 30typedef struct{ char *py;int k;}NAME;NAME NameList[HASH_LENGTH]; typedef struct{ char *py;int k;int si;//查找长度}HASH;HASH HashList[HASH_LENGTH]; void InitNameList(){ char *f;int r,s0,i;for (i=0; i<HASH_LENGTH; i++){NameList[i].py = new char[20];NameList[i].py[0] = 0;}strcpy(NameList[0].py, "lintingting"); strcpy(NameList[1].py, "chenxiaoping"); strcpy(NameList[2].py, "jianghaiyan"); strcpy(NameList[3].py, "wangtingting"); strcpy(NameList[4].py, "zhouhuihui"); strcpy(NameList[5].py, "zhuzhenguo"); strcpy(NameList[6].py, "wuqingwen"); strcpy(NameList[7].py, "chenzuopeng"); strcpy(NameList[8].py, "jinlining"); strcpy(NameList[9].py, "zhandakan"); strcpy(NameList[10].py, "linjiajia"); strcpy(NameList[11].py, "huangwenjun"); strcpy(NameList[12].py, "lizhongjing"); strcpy(NameList[13].py, "sushiding"); strcpy(NameList[14].py, "ouyangyaoyao"); strcpy(NameList[15].py, "chenwei");strcpy(NameList[16].py, "linxiaxiao"); strcpy(NameList[17].py, "zhanjie");strcpy(NameList[18].py, "baishujun"); strcpy(NameList[19].py, "gongqiaoqiao"); strcpy(NameList[20].py, "lvhaitao"); strcpy(NameList[21].py, "jiangqingsong"); strcpy(NameList[22].py, "gubaolong"); strcpy(NameList[23].py, "yehuaisong"); strcpy(NameList[24].py, "wangyuqin"); strcpy(NameList[25].py, "xuefeifei"); strcpy(NameList[26].py, "wujianshu"); strcpy(NameList[27].py, "zhanghuajiang"); strcpy(NameList[28].py, "zhengpan"); strcpy(NameList[29].py, "sudongdong");for(i=0;i<NAME_NO;i++){s0=0;f=NameList[i].py;for(r=0;*(f+r)!='\0';r++)s0=*(f+r)+s0;NameList[i].k=s0;}}void CreateHashList(){int i;for(i=0; i<HASH_LENGTH;i++){HashList[i].py=new char[20];HashList[i].py[0] = 0;HashList[i].k=0;HashList[i].si=0;}for(i=0;i<HASH_LENGTH;i++){int sum=0;int adr=(NameList[i].k)%M;int d=adr;if(HashList[adr].si==0) //如果不冲突{HashList[adr].k=NameList[i].k;HashList[adr].py=NameList[i].py;HashList[adr].si=1;}else //冲突{while (HashList[d].k!=0){d=(d+NameList[i].k%10+1)%M; //伪随机探测再散列法处理冲突sum=sum+1;};HashList[d].k=NameList[i].k;HashList[d].py=NameList[i].py;HashList[d].si=sum+1;}}}void FindList(){string name;int s0=0,r,sum=1,adr,d;cout<<"请输入人名的拼音:"<<endl;cin>>name;for(r=0;r<20;r++)s0+=name[r];adr=s0%M; //使用哈希函数d=adr;if(HashList[adr].k==s0)cout<<"姓名:"<<HashList[d].py<<endl<<"关键字:"<<s0<<endl<<"查找长度为: 1"<<endl;else if (HashList[adr].k==0)cout<<"无此记录!"<<endl;else{int g=0;while(g==0){d=(d+s0%10+1)%M;sum=sum+1;if(HashList[d].k==0){cout<<"无此记录!"<<endl;g=1;}if(HashList[d].k==s0){cout<<"姓名:"<<HashList[d].py<<endl<<"关键字:"<<s0<<endl<<"查找长度为:"<<sum<<endl;g=1;}};}}void Display(){int i;float average=0;cout<<"\n地址\t关键字\t\t搜索长度\tH(key)\t 姓名\n";for(i=0; i<50; i++){cout<<i<<" ";cout<<"\t"<<HashList[i].k<<" ";cout<<"\t\t"<<HashList[i].si<<" ";cout<<"\t\t"<<(HashList[i].k%M)<<" ";cout<<"\t "<<HashList[i].py<<" ";cout<<"\n";}for(i=0;i<HASH_LENGTH;i++)average+=HashList[i].si;average/=NAME_NO;cout<<"平均查找长度:ASL("<<NAME_NO<<")="<<average<<endl; }int main(){char x;InitNameList(); CreateHashList ();cout<<"d. 显示哈希表"<<endl<<"f. 查找"<<endl<<"任意键退出"<<endl<<"请选择:"<<endl;while(cin>>x){if(x=='d'){Display();cout<<endl;}else if(x=='f'){FindList();cout<<endl;}else break;}for (int i=0; i<HASH_LENGTH; i++){free(NameList[i].py);free(HashList[i].py);}return 0;}。
哈希表快速查找和插入数据的高效数据结构

哈希表快速查找和插入数据的高效数据结构哈希表是一种常用的数据结构,它能够提供快速的查找和插入操作,因此被广泛应用于各种计算机科学领域。
本文将介绍哈希表的原理、实现方式以及其在数据管理和算法设计中的应用。
一、哈希表的原理哈希表是一种基于哈希函数的数据结构,通过将关键字映射为数组的索引,实现对数据的高效存储和检索。
它将数据元素存储在数组中,每个数组位置称为“槽”,通过哈希函数将关键字映射为槽的索引。
哈希函数是哈希表的关键,它能够将任意大小的数据转换为固定大小的索引。
一个好的哈希函数应该能够将数据均匀地映射到各个槽,以避免冲突。
哈希函数的设计与关键字的特征密切相关,常见的哈希函数包括除留余数法、平方取中法和MD5等。
二、哈希表的实现方式1. 数组实现最简单直观的实现方式是使用数组来存储数据元素。
利用哈希函数计算出的索引即为数组的下标,通过数组的随机访问能够在常数时间内找到所需元素。
然而,在面对大量数据或者关键字冲突时,数组实现的性能会受到限制。
2. 链表解决冲突为了解决关键字冲突的问题,哈希表通常在每个槽上使用链表来存储多个元素。
当多个元素映射到同一个槽时,将它们按照插入顺序连接成链表。
这种方式可以保证插入和查找的平均时间复杂度为O(1),但在最坏情况下会退化为O(n)。
3. 开放寻址法解决冲突另一种常用的解决冲突的方式是开放寻址法(Open Addressing)。
当出现冲突时,该方法会依次检查下一个槽,直到找到一个空的槽或者遍历完所有槽。
常见的开放寻址法包括线性探测和二次探测等。
三、哈希表的应用1. 数据库管理哈希表可以用于数据库的索引结构,通过将关键字映射到存储位置,实现快速的数据检索。
在数据库的查询操作中,哈希表能够显著减少I/O操作,提高查询效率。
2. 缓存管理哈希表可以用于缓存的管理,通过将数据元素与其对应的内存位置关联,在缓存查找时能够快速定位到需要的数据。
这在大规模数据处理和高并发场景下非常有用。
哈希查找的判断实验报告

数据结构与算法设计实验报告(2016 — 2017 学年第1 学期)实验名称:年级:专业:班级:学号:姓名:指导教师:成都信息工程大学通信工程学院一、实验目的验证哈希查找算法二、实验要求(1)先创建一个数组类型的顺序表,以—1作为结束。
从键盘输入一组数据元素后,按顺序表的遍历输出,并打印显示。
(2)再以哈希函数方式,将数据元素放入哈希表中,并将哈希表输出,并打印显示。
采用线性探测法处理冲突。
注意:哈希表的下标和数据内容都显示到屏幕上。
(3)输入需要查找的任意元素的关键字,查找并输出该元素的位置下标序列号。
若有冲突,显示它原来的下标位置和新的下标位置。
若没有,也将找不到的信息反馈出来。
注意:用线性探测法处理冲突。
三、实验步骤1、创建工程(附带截图说明)2、根据算法编写程序(参见第六部分源代码)3、编译4、调试四、实验结果图五、心得体会本次实验练习了哈希表的创建与查找,虽然在实验过程中遇到了一些困难,但还是在老师及同学的帮助下顺利完成了。
之前学习C语言的时候基础不是很好,经过几次上级实验以及自己私下的练习,编写程序的过程中已经不会出现语法上的错误,节约了很多时间去思考算法设计。
实验过程中,在设计处理冲突的算法时,出现的漏洞较大,加之自己的逻辑产生混乱,出了很多差错。
在查阅资料后,理清了设计思路,从而解决了问题。
六、源代码要求:粘贴个人代码,以便检查。
#include <stdio.h>#define MAXSIZE#define HASHSIZE 13#define DELFLAG -1/*******关键字*******/typedef struct{int key;}DataType;/*******顺序表*******/typedef struct{DataType items[HASHSIZE];int length;}sqList;/*******哈希表*******/typedef struct{DataType data;int times;}HashTable[HASHSIZE];/*******哈希函数*******/int HashFunc(int key){return key %HASHSIZE;}/*******线性探查法*******/int Collision(int d){return(d+1)%HASHSIZE;}/*******哈希表的查找*******/int HashSearch(HashTable ht,DataType item){int addr;addr=HashFunc(item.key);while(ht[addr].data.key!=NULL&&ht[addr].data.key!=item.key) {printf("\n【%d】冲突地址:%d",item.key,addr);addr=Collision(addr);}if(ht[addr].data.key==item.key){return addr;}else{return -addr;}}/*******哈希表的插入*******/int HashInsert(HashTable ht,DataType item){int addr;addr=HashSearch(ht,item);if(addr>0){return 0;}ht[-addr].data=item;ht[-addr].times=1;return 1;}/*******哈希表的创建*******/void CreatHash(HashTable ht,DataType items[],int n) {int i;for(i=0;i<HASHSIZE;i++){ht[i].data.key=NULL;ht[i].times=0;}for(i=0;i<n;i++){HashInsert(ht,items[i]);}}/*******哈希表的删除*******/int HashDelete(HashTable ht,DataType item) {int addr;addr=HashSearch(ht,item);if(addr>=0){ht[addr].data.key=DELFLAG;return 1;}return 0;}/*******哈希表的显示*******/void DisplayHash(HashTable ht){int i;printf("\n\n哈希表\n\n哈希地址:");for(i=0;i<HASHSIZE;i++){printf("%d\t",i);}printf("\n关键字:\t");for(i=0;i<HASHSIZE;i++){if(ht[i].data.key!=NULL){printf("%d\t",ht[i].data.key);}else{printf("\t");}}printf("\n");}void main(){int i;int addr;int choice;HashTable ht;DataType item;sqList L;for(i=0;i<HASHSIZE;i++){L.items[i].key=0;}L.length=0;printf("\n---------哈希查找-------\n");printf("\n请输入要建立哈希表的关键字序列,以空格分隔,以-1结束\n"); for(i=0;i<HASHSIZE;i++){scanf("%d",&L.items[i].key);if(L.items[i].key==-1){break;}L.length++;}while(1){printf("\n---------哈希查找-------\n");printf("1:哈希表操作\n");printf("0:退出\n");printf("------------------\n");printf("请选择:");scanf("%d",&choice);switch(choice){case 1:{printf("\n顺序表为:");for(i=0;i<L.length;i++){printf("%d ",L.items[i].key);}CreatHash(ht,L.items,L.length);DisplayHash(ht);printf("\n请输入查找元素:");scanf("%d",&item.key);addr=HashSearch(ht,item);if(addr>=0){printf("\n【%d】查找到的地址为:\t%d\n",item.key,addr);}else{printf("\n未找到!\n");}break;}case 0:exit(0);default:{printf("\n错误!请重新输入...\n");break;}}getchar();}}。
如何通过数据结构实现快速查找

如何通过数据结构实现快速查找数据结构在计算机科学中起着至关重要的作用,其中快速查找是其中一个核心功能。
通过合理选择和设计数据结构,可以实现高效的查找操作,提高程序的运行效率。
本文将介绍如何通过数据结构实现快速查找,包括常用的数据结构及其查找算法。
一、哈希表哈希表(Hash Table)是一种通过哈希函数来计算数据存储位置的数据结构,具有快速查找的特点。
在哈希表中,每个元素都有一个对应的哈希值,通过哈希函数将元素映射到对应的位置。
在查找时,只需通过哈希函数计算元素的哈希值,即可快速定位到元素所在的位置,从而实现快速查找。
哈希表的查找时间复杂度为O(1),即在平均情况下,查找一个元素的时间与数据规模无关,具有非常高的效率。
然而,哈希表也存在一些缺点,如哈希冲突、空间利用率低等问题,需要通过合适的哈希函数和解决冲突的方法来优化。
二、二叉搜索树二叉搜索树(Binary Search Tree)是一种基于二叉树结构的数据结构,具有快速查找的特点。
在二叉搜索树中,每个节点的左子树中的所有节点的值均小于该节点的值,右子树中的所有节点的值均大于该节点的值。
通过这种有序性,可以通过比较大小的方式快速定位到目标元素。
在二叉搜索树中,查找操作的时间复杂度取决于树的高度,平均情况下为O(logn),最坏情况下为O(n)。
为了提高查找效率,可以通过平衡二叉搜索树(如AVL树、红黑树)来保持树的平衡,减少最坏情况的发生。
三、堆堆(Heap)是一种特殊的树形数据结构,常用于实现优先队列等场景。
在堆中,每个节点的值都大于等于(或小于等于)其子节点的值,称为最大堆(或最小堆)。
通过堆的性质,可以快速找到最大(或最小)值,实现快速查找。
堆的查找操作时间复杂度为O(1),即可以在常数时间内找到最大(或最小)值。
通过堆排序等算法,还可以实现对堆中元素的排序操作,提高程序的运行效率。
四、平衡查找树平衡查找树(Balanced Search Tree)是一种通过保持树的平衡来提高查找效率的数据结构。
哈希查找数据结构实验报告

引言概述:哈希查找是一种高效的数据结构,它通过将关键字映射为哈希码,将数据存储在哈希表中,从而实现快速的查找操作。
本实验报告将详细介绍哈希查找的原理、实现方法、效率分析以及实验结果,并探讨其在实际应用中的优缺点。
正文内容:一、哈希查找的原理1.1哈希函数的选择1.2冲突处理方法1.3哈希表的结构和特性1.4哈希查找的流程和算法二、哈希查找的实现方法2.1开放寻址法2.1.1线性探测法2.1.2二次探测法2.1.3双重散列法2.2链地质法2.2.1链表的表示与操作2.2.2链地质法的实现步骤2.2.3链地质法的优化方法三、哈希查找的效率分析3.1平均查找长度(ASL)的计算3.2填装因子与性能的关系3.3平均查找长度的简化计算3.4哈希查找的时间复杂度与空间复杂度分析四、实验结果与分析4.1构建哈希表的过程4.2不同冲突处理方法比较4.3不同填装因子下的性能变化4.4实验结果的优化策略4.5实验结果与理论分析的对比五、哈希查找的应用与优缺点5.1应用领域5.2优点与不足5.3哈希查找与其他查找方法的比较5.4未来发展方向和改进方法总结:哈希查找是一种高效的数据结构,它通过将关键字映射为哈希码,将数据存储在哈希表中,实现快速查找。
本文详细介绍了哈希查找的原理、实现方法、效率分析以及实验结果,并探讨了其在实际应用中的优缺点。
通过实验分析和对比,我们可以得出结论:哈希查找在一定填装因子下有着较高的查找效率和较低的空间复杂度,适用于大规模数据的快速查找和插入操作。
哈希查找也存在着冲突处理问题和哈希函数设计的困难等不足之处。
未来的改进方向可以是优化冲突处理方法和进一步提高哈希函数的质量,以提升整体性能和应用范围。
哈希表的查找

1
2 3
4
2)算法思想: 设n 个记录存放在一个有序顺序表 L 中,并按其关键 码从小到大排好了序。查找范围为l=0, r=n-1; 求区间中间位置mid=(l+r)/2; 比较: L[mid].Key = x,查找成功,返回mid,结束; L[mid].Key > x,r=mid-1; L[mid].Key < x,l=mid+1; 若l<=r 转2,否则查找失败,返回 0;
对查找表常用的操作有哪些?
查询某个“特定的”数据元素是否在表中; 查询某个“特定的”数据元素的各种属性; 在查找表中插入一元素; 从查找表中删除一元素。
9.1 基本概念
如何评估查找方法的优劣? 查找的过程就是将给定的值与文件中各记录的关 键字逐项进行比较的过程。所以用比较次数的平均值 来评估算法的优劣,称为平均查找长度(ASL: average search length)。i 1 i Ci ASL P
考虑对单链表结构如何折半查找? ——无法实现!
2)算法实现:
int Search_Bin ( SSTable ST, KeyType key ) { // 在有序表ST中折半查找其关键字等于key的数据元素。 // 若找到,则函数值为该元素在表中的位置,否则为0。 low = 1; high = ST.length; // 置区间初值 while (low <= high) { mid = (low + high) / 2; if (key == ST.elem[mid].key) return mid; // 找到待查元素 else if ( key < ST.elem[mid].key) high = mid - 1; // 继续在前半区间进行查找 else low = mid + 1; // 继续在后半区间进行查找 } return 0; // 顺序表中不存在待查元素 } // Search_Bin
数据结构 第9章 查找4-哈希表

6个元素用7个 地址应该足够!
1
2
23 9
3
4
39 25 11
5
6
H(25)=25%7=4 H(11)=11%7=4
有冲突!
在哈希查找方法中,冲突是不可能避免的,只能 尽可能减少。
所以,哈希方法必须解决以下两个问题:
1)构造好的哈希函数
(a)所选函数尽可能简单,以便提高转换速度; (b)所选函数对关键码计算出的地址,应在哈希地址集中 大致均匀分布,以减少空间浪费。
4、数字分析法
特点:某关键字的某几位组合成哈希地址。所选的位应当 是:各种符号在该位上出现的频率大致相同。 例:有一组(例如80个)关键码,其样式如下: 讨论: 3 4 7 0 5 2 4 ① 第1、2位均是“3和4”,第3位也 3 4 9 1 4 8 7 只有“ 7、8、9”,因此,这几位不 3 4 8 2 6 9 6 能用,余下四位分布较均匀,可作 3 4 8 5 2 7 0 为哈希地址选用。 3 4 8 6 3 0 5 3 4 9 8 0 5 8 ② 若哈希地址取两位(因元素仅80 3 4 7 9 6 7 1 个),则可取这四位中的任意两位组 3 4 7 3 9 1 9 合成哈希地址,也可以取其中两位与 位号:① ② ③ ④ ⑤ ⑥ ⑦ 其它两位叠加求和后,取低两位作哈 希地址。
11 22
△
47 92 16
3
▲
7
29
△
8
△
解释:
① 47、7(以及11、16、92)均是由哈希函数得到的没有冲突 的哈希地址; ② Hash(29)=7,哈希地址有冲突,需寻找下一个空的哈希地址: 由H1=(Hash(29)+1) mod 11=8,哈希地址8为空,因此将29存入。 ③ 另外,22、8、3同样在哈希地址上有冲突,也是由H1找到空 的哈希地址的。
自-精 品[精品]00《数据结构讲义》哈希表及其查找
![自-精 品[精品]00《数据结构讲义》哈希表及其查找](https://img.taocdn.com/s3/m/1e96a9fa52d380eb63946de0.png)
1.握散列相关知识。
学习要点包括各种散列函数的使用及其比较。
2.理解解决冲突的主要方法。
➢教学重点:哈希表及哈希查找。
解决地址冲突的方法。
➢教学难点:解决地址冲突的方法。
➢授课内容3哈希表查找(杂凑法)3.1哈希表与哈希方法以上讨论的查找方法,由于数据元素的存储位置与关键码之间不存在确定的关系,因此,查找时,需要进行一系列对关键码的查找比较,即“查找算法”是建立在比较的基础上的,查找效率由比较一次缩小的查找范围决定。
理想的情况是依据关键码直接得到其对应的数据元素位置,即要求关键码与数据元素间存在一一对应关系,通过这个关系,能很快地由关键码得到对应的数据元素位置。
【例3】11个元素的关键码分别为18,27,1,20,22,6,10,13,41,15,25。
选取关键码与元素位置间的函数为f(key)=key mod 111.通过这个函数对11个元素建立查找表如下:0 1 2 3 45 6 789 102211325 15276 18 412102.查找时,对给定值kx依然通过这个函数计算出地址,再将kx与该地址单元中元素的关键码比较,若相等,查找成功。
哈希表与哈希方法:选取某个函数,依该函数按关键码计算元素的存储位置,并按此存放;查找时,由同一个函数对给定值kx计算地址,将kx与地址单元中元素关键码进行比,确定查找是否成功,这就是哈希方法(杂凑法);哈希方法中使用的转换函数称为哈希函数(杂哈希表及其查找凑函数);按这个思想构造的表称为哈希表(杂凑表)。
对于n个数据元素的集合,总能找到关键码与存放地址一一对应的函数。
若最大关键为m,可以分配m个数据元素存放单元,选取函数f(key)=key即可,但这样会造成存储空间的很大浪费,甚至不可能分配这么大的存储空间。
通常关键码的集合比哈希地址集合大得多,因而经过哈希函数变换后,可能将不同的关键码映射到同一个哈希地址上,这种现象称为冲突(Collision),映射到同一哈希地址上的关键码称为同义词。
哈希表的建立和查找

实验四、哈希表的建立和查找一、实验目的:掌握哈希表的构造方法及其解决冲突的机制(开放地址法)。
二、实验内容:1、哈希表的概念哈希(hash)表又称为散列表,其基本思想是:P341。
2.处理冲突的方法--开放地址P3463.使用以下线性探测再散列的处理冲突方法实现哈希表。
ND=(D+di)%m (I=1,2,3…,I(I m-1))三、实验源程序(源程序中红色字体为完成部分)#include <iostream.h>#include <iomanip.h>#include <stdlib.h>#define MAXlENGTH 30enum HA VEORNOT{NULLKEY,HA VEKEY,DELKEY}; //哈希表元素的三种状态,没有记录、有记录、有过记录但已被删除class HashList{private:int *list;HA VEORNOT *elemflag;int mod;int count;public:HashList();HashList(int m);void InitHashList(int m);void ClearHashList();int HashFunction(int key);bool Search(int key,int &index);bool Insert(int key);bool Delete(int key);void Disp();};#include "hashlist.h"//构造函数1HashList::HashList(){mod=0;count=0;}//构造函数2,使用成员函数insert()实现初始化HashList::HashList(int m){if(m<1){cerr<<"哈希表的大小错误!"<<endl;}else{count=0;InitHashList(m);}}//初始化哈希表void HashList::InitHashList(int m){list=new int[m];elemflag=new HA VEORNOT[m];mod=m;for(int i=0;i<mod;i++){elemflag[i]=NULLKEY;}}//清空哈希表void HashList::ClearHashList(){if( count==0){cout<<"哈希表已经为空!";}else{//在此处添加你的代码int i;for(i=0;i<mod;i++){elemflag[i]=NULLKEY;}count = 0;}}//哈希函数int HashList::HashFunction(int key){if (mod==0){cerr<<"哈希表还没初始化!"<<endl;return -1;}else{return key%mod;}}bool HashList::Search(int key,int &index){if(mod==0){cerr<<"哈希表还没初始化!"<<endl;return false;}else{//在开放定址哈希表H中查找关键字为k的数据元素,若查找成功,返回ture//待查数据元素在表中的位置;否则返回-1。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
云南大学数学与统计学实验教学中心实验报告课程名称:数据结构与算法学期:2011-2012学年第二学期成绩:指导教师:xxx学生姓名:xxx学生学号:xxxxx实验名称:哈希表及其查找实验要求:必做实验学时:4(+2)学时实验编号:4(及5)实验日期:第6-8周完成日期:2012.5.10学院:数学与统计学院专业:信息与计算科学年级:2010级一、实验目的通过实验掌握散列存储的基本概念,进行哈希问题的处理,同时附带进行字符串的处理的练习。
二、实验内容为某单位的人名(n=30人)设计一个哈希表,使得平均查找长度<2,要求完成相应的哈希建表和查表。
三、实验环境Windows XP程序设计语言C四、实验过程1.实验要求:1、设人名长度<10个字符,用二维字符数组存储哈希表:char hash[ ][10];2、要求哈希函数用除留余数法,并用人名的10个字符代码和作为分子;用(补偿性)线性探测再散列处理冲突。
3、依题意有:平均查找长度=(1+1/(1-α))/2< 2,∴取α=0.6,由此哈希表长m=n/α=30/0.6=50; 所以有char hashlist [ 50][10];令:除留余数法中的P取47;(补偿性)线性探测再散列的地址:j=(j+Q)% m中的Q取17。
4、对程序结构的要求:①要求为哈希建表和哈希查表分别编写和设计相应的函数:createhash( ... ... ); hashsearch(... ...);②再设计一个哈希函数表的输出函数printhash( ),对构造的哈希表进行输出,注意输出格式要在屏幕好看,先输出序号(1~30),再输出该序号的人名或null,每行输出10项,共输出5行。
③还应有一个初始化char hashlist [ 50][10]的函数Inithashlist( ),初始时将50个人名全赋值为null.5、在主函数中:调用Inithashlist( )初始化哈希表;调用createhash( hashlist,30 )构造哈希表;调用printhash( )输出所建立的哈希表;接受待查找人名到字符数组name[ ];调用hashsearch(hashlist,name )进行查找,若查到显示"found!"并显示人名在数组中的序号;若未查到显示"no found!"[测试数据]:健表时输入以下数据:January February march april may june july august septemberOctober November DecemberSunday Monday Tuesday wednesday thurday f riday SaturdayOne two three four five six serve eight nine ten data[实现提示]:参照杨秀清主编《数据结构》西安电子科技大学出版社P171。
[附加要求]:1.在哈希查表时考虑插入。
当查找失败,且查找时的冲突次数<规定数字(如表长之半)时插入待查找的字符串,并给出“已插入”的显示;2.在哈希查表时考虑删除。
接受待删除人名到字符数组name[ ];在hash表中找到,并删除之。
须注意,删除后不能影响以后的查找。
2.实验设计的(各)流程图:(以下内容请同学认真填写)3.程序设计的关键代码及解释:(注意对程序代码给出必要的注解,保证可读性)#include<stdio.h>#define N 50#define D 30#define M 10int m,hi;/*-------------------------------------------------------------------*/main(){void Inithashlist(char a[N][M]);void createhash(char a[D][M],char h[N][M]);void hashsearch(char h[N][M],char a[1][M]);void printhash(char a[][M],int n);char a[M],hashlist[N][M],data[D][M]={/*----------------------------------------------------------*/"January", "February", "March", "April", "May","June", "July", "August", "September", "October","November", "December", "Sunday", "Monday", "Tuesday","Wednesday","Thursday", "Friday", "Saturday", "One","Two", "Three", "Four", "Five", "Six","Serve", "Eight", "Nine", "Ten", "Data"};/*----------------------------------------------------------*/Inithashlist(hashlist);createhash(data,hashlist);printhash(hashlist,50);printf("please enter the name:\n");gets(a);hashsearch(hashlist,a);getchar();getchar();}/*-------------------------------------------------------------------*/void Inithashlist(char a[N][M]){int i;for(i=0;i<N;i++) strcpy(a[i],"null");}/*-------------------------------------------------------------------*//*-------------------------------------------------------------------*/int H(int key,int p){return(key%p);}/*-------------------------------------------------------------------*//*-------------------------------------------------------------------*/void createhash(char a[D][M],char h[N][M]){int i,j,key=0,hi=0,di[N-1];for(i=0;i<N-1;i++) di[i]=i+1;for(i=0;i<D;i++){key=0;j=0;while(a[i][j])key+=a[i][j++];hi=H(key,47);if(!strcmp(h[hi-1],"null")) strcpy(h[hi-1],a[i]);else{m=0;while(strcmp(h[hi-1],"null")) hi=H(hi+17,N);strcpy(h[hi-1],a[i]);}}}/*-------------------------------------------------------------------*//*-------------------------------------------------------------------*/void hashsearch(char h[N][M],char a[M]){char ch2,ch[M]="yes",ch1[M]="yes";int i=0,j,key=0,hi=0;for(;a[i]!='\0';)key+=a[i++];hi=H(key,47);m=0;while(strcmp(h[hi-1],"null")&&strcmp(h[hi-1],a)&&(strcmp(h[hi-1],"Deleted"))) while(strcmp(h[hi-1],"null")) hi=H(hi+17,N);if(!strcmp(h[hi-1],a)){printf("**************\n");printf("found! \n");printf("[%d]%s\n",hi,h[hi-1]);printf("**************\n");while(strcmp(ch1,"No")&&strcmp(ch1,"no")){printf("Delete it?(Y/N)\n");scanf("%s",ch1);ch2=getchar();if(!strcmp(ch1,"Yes")||!strcmp(ch1,"yes")){strcpy(h[hi-1],"Deleted");printf("**************\n");printf("Deleted! \n");printf("**************\n");printhash(h,N);break;}}}else if(m<(N/2)||!(strcmp(h[hi-1],"Deleted"))){strcpy(h[hi-1],a);printf("**************\n");printf("已插入!\n");printf("[%d]%s\n",hi,h[hi-1]);printf("**************\n");printhash(h,N);}else{printf("**************\n");printf("no found!\n");printf("**************\n");}while(strcmp(ch,"No")&&strcmp(ch,"no")){printf("continue to search?(Yes/No)\n");scanf("%s",ch);ch2=getchar();if(!strcmp(ch,"Yes")||!strcmp(ch,"yes")){printf("please enter the name:\n");gets(a);hashsearch(h,a);}}}/*-------------------------------------------------------------------*//*-------------------------------------------------------------------*/void printhash(char a[][M],int n){int i;for(i=0;i<=8;i++){system("color 03");printf("[0%-d] %-11s",i+1,a[i]);if((i+1)%5==0) printf("\n");}for(i=9;i<n;i++){printf("[%-d] %-11s",i+1,a[i]);if((i+1)%5==0) printf("\n");}printf("---------------------");printf("-----------------END-----------------");printf("---------------------\n\n");}/*-------------------------------END---------------------------------*/4.实验(程序运行)结果的粘贴:(必需是你的程序运行结果)[01] Three [02] Nine [03] null [04] null [05] Monday [06] Wednesday [07] null [08] One [09] null [10] Six [11] null [12] null [13] May [14] Ten [15] null [16] null [17] Sunday [18] Five [19] Data [20] null [21] March [22] August [23] Thursday [24] null [25] January [26] June [27] Eight [28] null [29] null [30] October [31] November [32] Two [33] February [34] April [35] Serve [36] Four [37] null [38] null [39] December [40] null [41] null [42] September [43] Friday [44] July [45] null [46] Saturday [47] Tuesday [48] null [49] null [50] null--------------------------------------END--------------------------------------please enter the name:friday**************已插入![28]friday**************.........[26] June [27] Eight [28] friday [29] null [30] October .........--------------------------------------END--------------------------------------continue to search?(Yes/No)yesplease enter the name:friday**************found![28]friday**************Delete it?(Y/N)yes**************Deleted!**************.........[26] June [27] Eight [28] Deleted [29] null [30] October .........continue to search?(Yes/No)please enter the name:friday**************已插入![28]friday**************.........[26] June [27] Eight [28] friday [29] null [30] October.........continue to search?(Yes/No)no五、实验总结1.遇到的问题及分析:(请结合你的试验过程认真总结)①没采用(补偿性)线性探测再散列,导致第二次查找同一元素不能够找到;②删除元素之后用null代替,导致之后的查找操作失败2.解决方案(列出遇到的问题和解决办法,列出没有解决的问题):①改用(补偿性)线性探测再散列;②改用Deleted代替被删元素3.体会和收获。