哈希表的设计与实现

合集下载

c 语言 哈希表

c 语言 哈希表

C语言中的哈希表是一种数据结构,用于实现键-值对的存储和检索。

它通过将键映射到数组中的索引来实现高效的查找操作。

在C语言中,哈希表通常使用数组和链表的组合来实现。

一般情况下,哈希表包含一个固定大小的数组,每个数组元素称为一个桶(bucket)。

哈希函数将键映射到数组索引,每个键的哈希函数计算结果都应该是唯一的。

当需要插入一个键值对时,首先通过哈希函数计算键的哈希值,然后将键值对插入到对应索引的桶中。

如果多个键映射到相同的索引,这种情况称为哈希冲突。

为了解决冲突,每个桶通常是一个链表,新的键值对会被插入到链表的头部。

当需要查找一个键时,通过哈希函数计算键的哈希值,然后查找对应索引的桶。

在桶的链表中逐个比较键,直到找到对应的值或者链表结束。

需要注意的是,在哈希表中,哈希函数的设计非常重要,它应该尽可能均匀地将键分布到数组索引中,以减少哈希冲突的概率。

此外,当哈希表的负载因子过高时,即桶中键值对的数量过多,可能会导致性能下降,因此可能需要进行动态调整,例如重新分配更大的数组并重新插入所有键值对。

C语言中可以使用自定义的结构体来表示哈希表,包含数组和链表等成员变量。

操作哈希表的函数可以实现插入、查找、删除等操作,通过调用这些函数来使用哈希表。

总之,哈希表是一种在C语言中实现键-值对存储和检索的数据结构,通过哈希函数将键映射到数组索引,通过数组和链表的组合解决哈希冲突。

哈希表 哈希函数

哈希表 哈希函数

哈希表哈希函数哈希表是一种常见的数据结构,它通过哈希函数将键映射到存储位置,实现高效的数据查找和插入操作。

本文将从哈希函数的定义、设计原则、应用场景等方面进行介绍和探讨。

一、哈希函数的定义哈希函数是将任意长度的输入映射为固定长度输出的函数。

它的设计目标是将输入的数据分散到哈希表的不同槽位中,尽量避免冲突,使得数据能够均匀地分布在哈希表中。

二、哈希函数的设计原则1. 均匀性:好的哈希函数应该将输入的数据均匀地映射到哈希表的不同槽位中,避免冲突的发生。

常用的哈希函数有除留余数法、平方取中法等。

2. 确定性:同一个输入应该得到相同的输出,这样才能实现数据的查找和插入操作。

3. 高效性:哈希函数的计算速度应该尽可能快,以提高整体的性能。

三、哈希函数的应用场景1. 字典存储:哈希表可以用于实现字典存储结构,将键值对按照键的哈希值存储在哈希表中。

这样可以通过键快速地查找对应的值。

2. 缓存管理:哈希表可以用于实现缓存管理,将数据的哈希值作为索引,将数据存储在哈希表中。

这样可以加快数据的读取速度。

3. 唯一标识:哈希函数可以将数据转化为唯一的标识,用于数据的比较和去重。

例如,在分布式系统中,可以使用哈希函数将数据分配到不同的节点上。

四、哈希函数的性能评估1. 冲突率:冲突率是指哈希函数产生冲突的概率。

冲突率越低,哈希表的性能越好。

2. 均匀性:好的哈希函数应该将数据均匀地映射到哈希表的不同槽位中,避免槽位的过度拥挤。

3. 计算速度:哈希函数的计算速度应该尽可能快,以提高整体的性能。

五、哈希函数的优化策略1. 良好的分布性:选择合适的哈希函数,使得输入数据在哈希表中均匀分布,避免冲突的发生。

2. 良好的计算性能:选择计算速度较快的哈希函数,减少计算的时间消耗。

3. 避免冲突:可以通过增加哈希表的大小或者使用链表等方法来解决冲突的问题。

六、哈希函数的局限性1. 冲突:由于哈希函数的输出是有限的,而输入的数据是无限的,所以冲突是无法完全避免的。

hash的实现方式

hash的实现方式

hash的实现方式一、哈希的概念和作用哈希(Hash)是一种将任意长度的输入通过散列算法转换成固定长度输出的过程。

哈希算法的设计目标是将数据映射到尽可能唯一的哈希值,以便用于快速的数据存储和检索。

哈希的实现方式有很多种,下面将介绍几种常见的实现方式及其应用。

二、消息摘要算法消息摘要算法是哈希算法的一种常见实现方式,它将任意长度的数据转换为固定长度的摘要,也称为哈希值。

常见的消息摘要算法有MD5、SHA-1和SHA-256等。

这些算法具有以下特点:1. 输入数据的长度可以是任意的,输出的哈希值长度固定。

2. 相同的输入数据会产生相同的哈希值。

3. 即使输入数据只有微小的改变,也会产生完全不同的哈希值。

4. 很难通过哈希值反推出原始输入数据。

消息摘要算法广泛应用于数据完整性校验、数字签名、密码存储等场景。

三、密码哈希函数密码哈希函数是一种特殊的哈希函数,它在保证哈希性质的同时,加入了一些特殊的设计,以增加密码的安全性。

常见的密码哈希函数有bcrypt和scrypt等。

这些函数具有以下特点:1. 输入数据的长度可以是任意的,输出的哈希值长度固定。

2. 相同的输入数据会产生相同的哈希值。

3. 为了增加安全性,这些函数会加入盐(salt)和迭代次数的概念。

4. 盐是一个随机生成的字符串,用于增加哈希值的复杂度。

5. 迭代次数表示对哈希算法的多次迭代,以增加计算时间,提高破解难度。

密码哈希函数广泛应用于用户密码的存储和验证,以及安全敏感数据的保护。

四、哈希表哈希表是一种将键(Key)映射到值(Value)的数据结构,它通过哈希函数将键转换为索引,然后将值存储在对应的索引位置。

哈希表的实现方式有很多种,其中最常见的是使用数组和链表的组合。

哈希表具有以下特点:1. 通过哈希函数将键转换为索引,实现快速的插入、查找和删除操作。

2. 哈希函数应尽可能将键均匀地映射到索引,以避免冲突。

3. 冲突是指不同的键经过哈希函数计算后得到相同的索引,可以通过链表解决。

hashtable底层原理

hashtable底层原理

hashtable底层原理Hashtable底层原理Hashtable是一种常见的数据结构,它可以快速地进行数据的查找和插入操作。

在Java中,Hashtable是一个非常常用的类,它的底层实现是基于哈希表的。

本文将从哈希表的基本原理、哈希函数的设计、哈希冲突的处理以及Hashtable的实现等方面来介绍Hashtable的底层原理。

一、哈希表的基本原理哈希表是一种基于数组的数据结构,它通过哈希函数将数据映射到数组的某个位置上。

哈希函数的设计是哈希表的关键,它决定了数据在数组中的位置。

哈希表的基本操作包括插入、查找和删除。

插入操作将数据插入到哈希表中,查找操作根据关键字查找数据,删除操作将数据从哈希表中删除。

二、哈希函数的设计哈希函数的设计是哈希表的关键,它决定了数据在数组中的位置。

哈希函数的设计需要满足以下几个条件:1. 映射范围:哈希函数需要将数据映射到数组的某个位置上,因此哈希函数的返回值需要在数组的范围内。

2. 均匀性:哈希函数需要将数据均匀地映射到数组的各个位置上,这样可以避免哈希冲突的发生。

3. 碰撞概率:哈希函数需要尽可能地减少哈希冲突的发生,这样可以提高哈希表的效率。

常见的哈希函数包括直接寻址法、除留余数法、数字分析法、平方取中法、折叠法等。

三、哈希冲突的处理哈希冲突是指不同的数据经过哈希函数映射到数组的同一个位置上。

哈希冲突的发生是不可避免的,因此需要采取一些方法来处理哈希冲突。

常见的哈希冲突处理方法包括开放地址法和链地址法。

开放地址法是指当哈希冲突发生时,继续寻找数组中的下一个空位置,直到找到为止。

链地址法是指将哈希冲突的数据存储在链表中,每个数组位置上存储一个链表头指针,指向链表的第一个节点。

四、Hashtable的实现Hashtable是Java中的一个非常常用的类,它的底层实现是基于哈希表的。

Hashtable的实现采用了链地址法来处理哈希冲突。

当哈希冲突发生时,将数据存储在链表中,每个数组位置上存储一个链表头指针,指向链表的第一个节点。

数据结构课程设计--哈希表实验报告

数据结构课程设计--哈希表实验报告

福建工程学院课程设计课程:算法与数据结构题目:哈希表专业:网络工程班级:xxxxxx班座号:xxxxxxxxxxxx姓名:xxxxxxx2011年12 月31 日实验题目:哈希表一、要解决的问题针对同班同学信息设计一个通讯录,学生信息有姓名,学号,电话号码等。

以学生姓名为关键字设计哈希表,并完成相应的建表和查表程序。

基本要求:姓名以汉语拼音形式,待填入哈希表的人名约30个,自行设计哈希函数,用线性探测再散列法或链地址法处理冲突;在查找的过程中给出比较的次数。

完成按姓名查询的操作。

运行的环境:Microsoft Visual C++ 6.0二、算法基本思想描述设计一个哈希表(哈希表内的元素为自定义的结构体)用来存放待填入的30个人名,人名为中国姓名的汉语拼音形式,用除留余数法构造哈希函数,用线性探查法解决哈希冲突。

建立哈希表并且将其显示出来。

通过要查找的关键字用哈希函数计算出相应的地址来查找人名。

通过循环语句调用数组中保存的数据来显示哈希表。

三、设计1、数据结构的设计和说明(1)结构体的定义typedef struct //记录{NA name;NA xuehao;NA tel;}Record;录入信息结构体的定义,包含姓名,学号,电话号码。

typedef struct //哈希表{Record *elem[HASHSIZE]; //数据元素存储基址int count; //当前数据元素个数int size; //当前容量}HashTable;哈希表元素的定义,包含数据元素存储基址、数据元素个数、当前容量。

2、关键算法的设计(1)姓名的折叠处理long fold(NA s) //人名的折叠处理{char *p;long sum=0;NA ss;strcpy(ss,s); //复制字符串,不改变原字符串的大小写strupr(ss); //将字符串ss转换为大写形式p=ss;while(*p!='\0')sum+=*p++;printf("\nsum====================%d",sum);return sum;}(2)建立哈希表1、用除留余数法构建哈希函数2、用线性探测再散列法处理冲突int Hash1(NA str) //哈希函数{long n;int m;n=fold(str); //先将用户名进行折叠处理m=n%HASHSIZE; //折叠处理后的数,用除留余数法构造哈希函数return m; //并返回模值}Status collision(int p,int c) //冲突处理函数,采用二次探测再散列法解决冲突{int i,q;i=c/2+1;while(i<HASHSIZE){if(c%2==0){c++;q=(p+i*i)%HASHSIZE;if(q>=0) return q;else i=c/2+1;}else{q=(p-i*i)%HASHSIZE;c++;if(q>=0) return q;else i=c/2+1;}}return UNSUCCESS;}void benGetTime();}else printf("\n此人不存在,查找不成功!\n");benGetTime();}(4)显示哈希表void ShowInformation(Record* a) //显示输入的用户信息{int i;system("cls");for( i=0;i<NUM_BER;i++)printf("\n第%d个用户信息:\n 姓名:%s\n 学号:%s\n 电话号码:%s\n",i+1,a[i].name,a[i].xuehao,a[i].tel);}(5)主函数的设计void main(int argc, char* argv[]){Record a[MAXSIZE];int c,flag=1,i=0;HashTable *H;H=(HashTable*)malloc(LEN);for(i=0;i<HASHSIZE;i++){H->elem[i]=NULL;H->size=HASHSIZE;H->count=0;}while (1){ int num;printf("\n ");printf("\n 欢迎使用同学通讯录录入查找系统");printf("\n 哈希表的设计与实现");printf("\n 【1】. 添加用户信息");printf("\n 【2】. 读取所有用户信息");printf("\n 【3】. 以姓名建立哈希表(再哈希法解决冲突) ");printf("\n 【4】. 以电话号码建立哈希表(再哈希法解决冲突) ");printf("\n 【5】. 查找并显示给定用户名的记录");printf("\n 【6】. 查找并显示给定电话号码的记录");printf("\n 【7】. 清屏");printf("\n 【8】. 保存");printf("\n 【9】. 退出程序");printf("\n 温馨提示:");printf("\n Ⅰ.进行5操作前请先输出3 ");printf("\n Ⅱ.进行6操作前请先输出4 ");printf("\n");printf("请输入一个任务选项>>>");printf("\n");scanf("%d",&num);switch(num){case 1:getin(a);break;case 2:ShowInformation(a);break;case 3:CreateHash1(H,a); /* 以姓名建立哈希表*/break;case 4:CreateHash2(H,a); /* 以电话号码建立哈希表*/break;case 5:c=0;SearchHash1(H,c);break;case 6:c=0;SearchHash2(H,c);break;case 7:Cls(a);break;case 8:Save();break;case 9:return 0;break;default:printf("你输错了,请重新输入!");printf("\n");}}system("pause");return 0;3、模块结构图及各模块的功能:四、源程序清单:#include<stdio.h>#include<stdlib.h>#include<string.h>#include <windows.h>#define MAXSIZE 20 #define MAX_SIZE 20 #define HASHSIZE 53 #define SUCCESS 1#define UNSUCCESS -1#define LEN sizeof(HashTable)typedef int Status;typedef char NA[MAX_SIZE];typedef struct {NA name;NA xuehao;NA tel;}Record;typedef struct {Record *elem[HASHSIZE]; int count; int size; }HashTable;Status eq(NA x,NA y) {if(strcmp(x,y)==0)return SUCCESS;else return UNSUCCESS;}Status NUM_BER;void getin(Record* a) {int i;system("cls");printf("输入要添加的个数:\n");scanf("%d",&NUM_BER);for(i=0;i<NUM_BER;i++){printf("请输入第%d个记录的姓名:\n",i+1);scanf("%s",a[i].name);printf("请输入%d个记录的学号:\n",i+1);scanf("%s",a[i].xuehao);printf("请输入第%d个记录的电话号码:\n",i+1);scanf("%s",a[i].tel);}}void ShowInformation(Record* a){int i;system("cls");for( i=0;i<NUM_BER;i++)printf("\n第%d个用户信息:\n 姓名:%s\n 学号:%s\n 电话号码:%s\n",i+1,a[i].name,a[i].xuehao,a[i].tel);}void Cls(Record* a){printf("*");system("cls");}long fold(NA s){char *p;long sum=0;NA ss;strcpy(ss,s);strupr(ss);p=ss;while(*p!='\0')sum+=*p++;printf("\nsum====================%d",sum);return sum;}int Hash1(NA str){int m;n=fold(str);m=n%HASHSIZE;return m;}int Hash2(NA str){long n;int m;n = atoi(str);m=n%HASHSIZE;return m;}Status collision(int p,int c){int i,q;i=c/2+1;while(i<HASHSIZE){if(c%2==0){c++;q=(p+i*i)%HASHSIZE;if(q>=0) return q;else i=c/2+1;}else{q=(p-i*i)%HASHSIZE;c++;if(q>=0) return q;else i=c/2+1;}}return UNSUCCESS;}void benGetTime();void CreateHash1(HashTable* H,Record* a){ int i,p=-1,c,pp;system("cls"); benGetTime();for(i=0;i<NUM_BER;i++){p=Hash1(a[i].name);pp=p;while(H->elem[pp]!=NULL) {pp=collision(p,c);if(pp<0){printf("第%d记录无法解决冲突",i+1);continue;}}H->elem[pp]=&(a[i]);H->count++;printf("第%d个记录冲突次数为%d。

哈希实验报告

哈希实验报告

引言概述:本文旨在对哈希实验进行报告,重点介绍哈希实验的二次探测法、哈希函数、哈希表的查找、插入与删除操作,并分析实验结果。

通过本实验的开展,我们对哈希算法的原理、实现和性能有了更深入的理解,也增加了对数据结构的实践能力。

正文内容:一、二次探测法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.实验的意义与启示总结:通过对哈希实验的详细阐述,我们对二次探测法、哈希函数、哈希表的查找、插入与删除操作有了更深入的了解。

实验结果与分析表明,在哈希表的实现中,选择合适的哈希函数、解决哈希冲突以及优化插入与删除操作,对提高哈希表的性能至关重要。

哈希算法作为一种重要的数据结构应用,具有广泛的应用前景,在实际问题中具有重要的实践意义。

通过本次实验,我们不仅提升了对数据结构的理论理解,也增强了数据结构算法的实践能力,为今后的学习与研究打下了坚实的基础。

第七章-哈希表

第七章-哈希表

哈希表又称散列表,实际上就是一个数组。

哈希函数是一个用来求存储在哈希的关键字在哈希表的地址下标的函数.比如一个哈希表int hashtable[5];现在有下面4个数要存入到哈希表中:(3,15,22,24)给定一个哈希函数: H(k)=k % 5最终数据存储如下图:理想情况下,哈希函数在关键字和地址之间建立了一个一一对应关系,从而使得查找只需一次计算即可完成。

由于关键字值的某种随机性,使得这种一一对应关系难以发现或构造。

因而可能会出现不同的关键字对应一个存储地址。

即k1≠k2,但H(k1)=H(k2),这种现象称为冲突。

把这种具有不同关键字值而具有相同哈希地址的对象称“同义词”。

在大多数情况下,冲突是不能完全避免的。

这是因为所有可能的关键字的集合可能比较大,而对应的地址数则可能比较少。

对于哈希技术,主要研究两个问题:(1)如何设计哈希函数以使冲突尽可能少地发生。

(2)发生冲突后如何解决。

哈希函数的构造方法:构造好的哈希函数的方法,应能使冲突尽可能地少,因而应具有较好的随机性。

这样可使一组关键字的散列地址均匀地分布在整个地址空间。

根据关键字的结构和分布的不同,可构造出许多不同的哈希函数。

1.直接定址法直接定址法是以关键字k本身或关键字加上某个数值常量c作为哈希地址的方法。

该哈希函数H(k)为:H(k)=k+c (c≥0)这种哈希函数计算简单,并且不可能有冲突发生。

当关键字的分布基本连续时,可使用直接定址法的哈希函数。

否则,若关键字分布不连续将造成内存单元的大量浪费。

2.除留余数法(注意:这种方法常用)取关键字k除以哈希表长度m所得余数作为哈希函数地址的方法。

即:H(k)=k %m这是一种较简单、也是较常见的构造方法。

这种方法的关键是选择好哈希表的长度m 。

使得数据集合中的每一个关键字通过该函数转化后映射到哈希表的任意地址上的概率相等。

理论研究表明,在m 取值为素数(质数)时,冲突可能性相对较少。

哈希表——线性探测法、链地址法、查找成功、查找不成功的平均长度

哈希表——线性探测法、链地址法、查找成功、查找不成功的平均长度

哈希表——线性探测法、链地址法、查找成功、查找不成功的平均长度⼀、哈希表1、概念哈希表(Hash Table)也叫散列表,是根据关键码值(Key Value)⽽直接进⾏访问的数据结构。

它通过把关键码值映射到哈希表中的⼀个位置来访问记录,以加快查找的速度。

这个映射函数就做散列函数,存放记录的数组叫做散列表。

2、散列存储的基本思路以数据中每个元素的关键字K为⾃变量,通过散列函数H(k)计算出函数值,以该函数值作为⼀块连续存储空间的的单元地址,将该元素存储到函数值对应的单元中。

3、哈希表查找的时间复杂度哈希表存储的是键值对,其查找的时间复杂度与元素数量多少⽆关,哈希表在查找元素时是通过计算哈希码值来定位元素的位置从⽽直接访问元素的,因此,哈希表查找的时间复杂度为O(1)。

⼆、常⽤的哈希函数1. 直接寻址法取关键字或者关键字的某个线性函数值作为哈希地址,即H(Key)=Key或者H(Key)=a*Key+b(a,b为整数),这种散列函数也叫做⾃⾝函数.如果H(Key)的哈希地址上已经有值了,那么就往下⼀个位置找,知道找到H(Key)的位置没有值了就把元素放进去.2. 数字分析法分析⼀组数据,⽐如⼀组员⼯的出⽣年⽉,这时我们发现出⽣年⽉的前⼏位数字⼀般都相同,因此,出现冲突的概率就会很⼤,但是我们发现年⽉⽇的后⼏位表⽰⽉份和具体⽇期的数字差别很⼤,如果利⽤后⾯的⼏位数字来构造散列地址,则冲突的⼏率则会明显降低.因此数字分析法就是找出数字的规律,尽可能利⽤这些数据来构造冲突⼏率较低的散列地址.3. 平⽅取中法取关键字平⽅后的中间⼏位作为散列地址.⼀个数的平⽅值的中间⼏位和数的每⼀位都有关。

因此,有平⽅取中法得到的哈希地址同关键字的每⼀位都有关,是的哈希地址具有较好的分散性。

该⽅法适⽤于关键字中的每⼀位取值都不够分散或者较分散的位数⼩于哈希地址所需要的位数的情况。

4. 折叠法折叠法即将关键字分割成位数相同的⼏部分,最后⼀部分位数可以不同,然后取这⼏部分的叠加和(注意:叠加和时去除进位)作为散列地址.数位叠加可以有移位叠加和间界叠加两种⽅法.移位叠加是将分割后的每⼀部分的最低位对齐,然后相加;间界叠加是从⼀端向另⼀端沿分割界来回折叠,然后对齐相加.5. 随机数法选择⼀个随机数,去关键字的随机值作为散列地址,通常⽤于关键字长度不同的场合.6. 除留余数法取关键字被某个不⼤于散列表表长m的数p除后所得的余数为散列地址.即H(Key)=Key MOD p,p<=m.不仅可以对关键字直接取模,也可在折叠、平⽅取中等运算之后取模。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

令胆嗲院计算机科嗲b练水系课程设计报告2007 2008 学年第 2 学期课程数据结构与算法课程设计名称哈希表的设计与实现学生姓名学号0604011026专业班级06计科(1)指导教师2008 年9 月课程设计题目:(哈希表的设计与实现的问题〉设计哈希表实现电话号码查询系统。

设计程序完成以下要求:(1)设每个记录有下列数据项:电话号码、用户名、地址:(2)从键盘输入各记录,分别以电话号码和用户名为关键字建立晗希表;(3)采用再哈希法解决冲突;(4)查找并显示给定电话号码的记录:(5)查找并显示给定用户的记录。

一、问题分析和任务定义1、问题分析要完成如下要求:设计晗希表实现电话号码查询系统。

实现本程序需要解决以下几个问题:(1) 如何设计一个结点使该结点包括电话号码、用户名、地址。

(2) 如何分别以电话号码和用户名为关键字建立哈希表。

(3) 如何利用再晗希法解决冲突。

(4) 如何实现用晗希法查找并显示给定电话号码的记录。

(5) 如何查找并显示给定用户的记录。

2、任务定义由问题分析知,本设计主要要求分别以电话号码和用户名为关键字建立晗希表,并实现查找功能。

所以本设计的核心问题是如何解决散列的问题,亦即设计一个良好的哈希表。

由于结点的个数无法确认,并且如果采用线性探测法散列算法,删除结点会引起“信息丢失”的问题。

所以采用链地址法散列算法。

采用链地址法,当出现同义词冲突时,使用链表结构把同义词链接在一起,即同义词的存储地址不是散列表中其他的空地址。

决的是定义链表结点,在链地址法中,每个结点对应一个链表结点,它由三个首先,解域组成,而由于该程序需要分别用电话号码和用户名为关键字建立晗希表,所以该链表结点它是由四个域组成.name[8]、num[ll]和address[20]都是char浮点型,输入输出都只能是浮点型的。

采用链地址法,其中的所有同义词构成一个单链表,再由一个表头结点指向这个单链表的第一个结点。

这些表头结点组成一个一维数组,即哈希表。

数组元素的下标对应由散列函数求出的散列地址。

拉链法处理冲突的散列表结构:|||||3、主程序分析本题目最主要的要求是设计散列函数,本程序需要设计两个散列函数才能解决问题,程序需要分别为以电话号码和用户名为关键字建立哈希表。

所以要分别以用户名、号码为关键字建立两个散列画数,具体思路为:后对20求余。

得到的对于以号码为关键字的散列函数,是将十一个数字全部相加,然数作为地址。

对于以用户名为关键字的散列函数,是将所有字母的ASCLL码值相加,然后对20求余。

要添加用户信息,即要有实现添加结点的功能的函数,所以要设计一个必须包括一个输入结点信息、添加结点的函数:要实现查找函数,则必须包括一个查找结点的函数;另外还有一个必不可少的就是运行之后要有一个主菜单,即要设计一个主函数(mai n())。

4、测试数据的选择最后,程序完成后要对程序进行编译调试,执行后要选择数据进行测试,这里选择的测试数据为:l、姓名:张三电话号码:地址:合肥2、姓名:Jack 电话号码:地址:Shanghai三、概要设计和数据结构选择本设计涉及到的数据结构为:哈希表。

要求输入电话号码、用户名、地址三个信息,并要求分别以电话号码和用户名为关键字进行查找,所以本问题要用到两个晗希函数,进行哈希查找。

在链地址法中,每个结点对应一个链表结点,它由三个域组成,而由于该程序需要分别用电话号码和用户名为关键字建立哈希表,所以该链表结点它是由四个域组成,链地址法结点结构如图:|阳e[8]I川[口J l a抽出s[20] I next其中name[8]和num[ll]是分别为以电话号码和用户名为关键字域,存放关键字(key ) ; address[20](data)为结点的数据域,用来存储用户的地址。

Next指针是用来指向下一个结点的地址。

主要算法的流程图如下:以号码为关键字的H a s h()函数流程图开始取整型n um[2]赋给k eyi从3开始取Key=key+(int) num[i]i++Key=key%20结束以姓名为关键字的H ash O函数流程图/开始取整型name[O]赋给key2i从0开始取K ey2+=name[i]i++K ey2:::key%20结束添加结点信息流程图:开始申请新的结点 newp hone,newname 即新的号码和名字Newphone=input()Newname 指向n ewphone调用h ash()函数调用h ash()函数拉链法处理冲突利用用户名为关键字插入结束按姓名查找流程图:开始调用h ash()函数中新结点q指向phone[key]->nextq=q->n ext输出无记录q 不为空输出相应记录结束按号码查找流程图:开始调用b ash2()函数中新结点q指向pbone[key]->nextq=q->n ex t输出无记录q 不为空输出相应记录结束初始化散列链表 (1) 并为 其动态分配内存空 间初始化散列链表 ( 2) 并为 其动态分配内存空 间主程序流程图Menu () 主菜单结束进行姓名散1添加记录 a pend()进行号码散列 list ()号码散列 结果清空 creat();creat2()列表己清 空退出系统 return Ov .. . ..四、详细设计和编码首先定义结点结构体类型,在链地址法中,每个结点对应一个链表结点,它由三个域组成,而由于该程序需要分别用电话号码和用户名为关键字建立哈希表,所以该链表结点它是由四个域组成,链地址法结点结构如图:I n棚e[s]I川其中nam e[8]和num[ll]是分别为以电话号码和用户名为关键字域(k ey),存放关键字:a ddr ess[20]为结点的数据域(d ata),用来存储用户的地址信息。

n ex t指针是用来指向下一个结点的地址。

u n s ign e d in t k ey 和u n s ign e d in t k ey2 分别被定义为电话号码和用户名关键字。

程序的主要模块如下:*****串******************程序部分源代码中串*串*串*串*串*丰*************1、建立节点st ru ct node H建节点c har name[8],address[20]矿/节点中要包含用户名,用户地址,电话号码以及指向下一个结点的指针char num(ll];node * next;ty p e d ef node* pnode; //typedef 可以为一个己有的数据类型声明多个别名,这里为该类型声明了两个指针ty p e d ef node* mingzi;node **ph o ne ;node肺nam;nod e*a;2、对哈希函数的定义本程序要设计两个h as h O函数,分别对应电话号码和用户名。

本设计中对散列函数选择的是除留余数法,即对关键字进行模运算,将运算结果所得的余数作为关键字(或结点〉的存储地址,即************************程序部分源代码*牢牢牢牢牢牢牢牢牢牢串串串串串串串串*本*本*中a),•oid h as h(c har num[ll])II以电话号码为关键字建立哈希函数ke y=(int)num [2];while(num[i]!=NULL)ke y +=(int )num[i];1++;key =ke y %20;b )void bash2(c har name[8]) II 以用户名为关键字建立晗希函数int i = 1;key2=(int )name [O];while(name[i]!=NULL)ke y 2+=(int )name [i];’++;ke y 2=ke y 2%20;然后,建立结点 ,并添加结点用链地址法解决冲突 。

建立结点应包括动态申请内 存空间。

向结点中输入信息。

同时将结并且,需要两个建立散列链表的函数 ,分别动态申请一定的空间 ,用于动态申请散列 链表。

vo id creat β()用来动态创建以电话号码为关键字的链表数组,void create2()用来动态创 建以用户名为关键字的链表数组。

************串串**********程序部分源代码********************串*串*丰v oid create() II 新建号码节点 phone[i]=new nod e;phone[i]->next=NULL;int i ;phone =new pnode[20]; fl 动态创建对象数组for(i=O;i<20;i++)v oid create2() II新建姓名节点nam[i]=ne w node;int i; nam[i]->next=NULL ;nam=new mingzi[20];for(i=O;i<20;i叫同样,需要两个显示链表的函数,利用f or 循环和w hile 语句将表中信息按要求输出来。

3. 哈希查找想要实现查找功能,同样需要两个查找函数,无论以用户名还是以电话号码为关键字,果是以电话号码为关键字,比较首先,都需要利用h ash函数来计算出地址。

再通过比对,如其电话号码是否相同,如果相同则输出该结点的所有信息,如果以用户名为关键字,则比较用户名是否相同,如果相同则输出该结点的所有信息。

如果找不到与之对应相同的,则输出“无此记录,,。

************************程序部分源代码****串串*******************a)、void find(c har num[ll])施以电话号码为关键字的哈希表中查找用户信息hash(num);node *q=phone[ke y]->n ext;w hile(q!= NULL)if(s trcmp(num,q->num)==O)bre ak;q=q->ne x t;if(q)printf(”%s_%s_%s\n",q->name,q->a d dre邸q->num);el s e printf(无J1t记录飞n");b)、vo id f md2(c har name[S])II在以用户名为关键字的哈希表中查找用户信息hash2(nam e);node*q=nam[key2]->next;w hile(q!=NULL)i f(st r c mp(name,q->nam e)==O)break;q=q->next;if(q)q->nam e,q->addre ss,q->nUJD);printf(”%s_%s_%s恼”,el s e printf (无此记录飞n");3、主函数本程序需要创建一个主菜单和一个主函数,主菜单便于用户的使用,主函数中,包括所有功能对应的数值,使之和主菜单相对应。

相关文档
最新文档