数据结构哈希表设计

合集下载

哈希表的定义和工作原理

哈希表的定义和工作原理

哈希表的定义和工作原理
哈希表(Hash Table),又称作散列表或哈希映射,是一种用
于存储键值对的数据结构。

它通过哈希函数将键映射到存储位置,从而快速定位到对应的值。

哈希表的工作原理如下:
1. 创建一个固定大小的数组(哈希表),数组的每个元素都是一个链表的头指针。

2. 当插入一个键值对时,将键通过哈希函数计算得到一个哈希值,然后将该键值对存储在哈希值对应的链表中。

3. 当需要查找某个键对应的值时,先将键通过哈希函数计算得到哈希值,然后在哈希值对应的链表中找到该键对应的值。

4. 如果多个键通过哈希函数计算得到的哈希值相同,即出现哈希冲突,则在链表中进行线性搜索或使用其他解决冲突的方法。

哈希表的特点包括:
- 查找、插入和删除操作的平均时间复杂度为O(1),在某些情
况下可以达到O(1)。

- 哈希表的性能依赖于哈希函数的选择和哈希表的负载因子。

- 负载因子表示哈希表中元素的个数与哈希表大小的比值,负
载因子越高,哈希冲突的可能性越高,性能下降。

需要注意的是,哈希函数的设计很重要,好的哈希函数应该尽可能地使得键的哈希值均匀分布,减少哈希冲突的可能性。

常见的哈希函数包括取余法、乘法散列法、折叠法等。

另外,为了解决哈希冲突,常用的方法包括拉链法、开放定址法等。

Python中的哈希表

Python中的哈希表

Python中的哈希表哈希表是一种基本的数据结构,是在计算机科学中被广泛使用的一种算法,也被称为散列表。

在计算机程序中,哈希表是一种根据关键字直接访问数据的数据结构。

哈希表的设计基于哈希函数,它将输入数据转换成一串数字,这个数字就可以唯一地对应输入数据在哈希表中的位置,可以实现非常快速的查找、插入和删除操作。

哈希表主要的优点是它提供了常数级别的时间复杂度,所以它将从大量数据中搜索或枚举出特定条目的工作转变为了对一组异构数据的随机访问,这使得哈希表在计算机工程的许多领域都有广泛的应用。

例如,哈希表在数据库系统、索引系统、网络协议、编译器等各种领域中都得到了广泛的应用。

哈希表的实现通常使用哈希函数将关键字映射到哈希表中的位置,这个位置称为“哈希值”或“索引”,然后将数据存储在这个位置上。

哈希函数从关键字中计算出哈希值(或索引),所以当使用哈希表时需要选择适当的哈希函数,以确保最小化哈希冲突(即两个不同的关键字映射到同一个哈希值上)的概率。

哈希表的核心思想是将大量数据映射到更小的区域(通常是哈希表中的特定位置)中,以便于对它们进行查询、浏览、修改和删除。

具体来说,哈希表的构建要求程序员找到一个适当的哈希函数。

最好的哈希函数往往具有以下几个特性:(1)哈希函数应该足够简单,可以快速、有效地计算出哈希值。

(2)哈希函数应该是确定的,即对于特定的关键字,哈希函数应该始终返回相同的哈希值。

(3)哈希函数应该将不同的关键字分散到哈希表的各个位置,以确保最小化哈希冲突的概率。

(4)哈希函数应该尽可能均匀地将关键字分布在哈希表的不同位置上,从而避免过多的哈希冲突,保证哈希表的性能。

哈希表可以通过不同的底层数据结构来实现,通常使用数组配合链表或红黑树来实现,具体实现细节要根据实际应用场景来考虑。

在一些应用场景中,例如在大量数据的情况下,链式哈希表的效率会大幅下降,此时更适合使用基于红黑树的哈希表或线性哈希表。

另外,哈希表的实现需要考虑压缩问题,即当哈希表中的数据存储超过一定数量后,如何迅速地扩充存储区域,并保证数据的存储连续性和不变性。

哈希表数据结构例题

哈希表数据结构例题

哈希表数据结构例题哈希表(HashTables)是一种用于存储数据的结构,它根据键(key)计算出一个值(value),从而将数据存储到对应的位置上。

它是一种用空间换取时间的算法,通过哈希函数将键值转化为整数,并将其映射到一个“桶”中,快速定位查找所需的数据,从而大大减少搜索时间。

哈希表也常用于排序、缓存、验证数据的完整性等方面。

哈希表的原理哈希表的主要原理就是使用一种称为哈希函数(hash function)的算法来将键值转化为整数,然后将其映射到一个“桶”中,也就是一个包含要存储的值的有序数组。

哈希函数是把任意字符串或其他数据类型,转换为一个固定长度的整数,也就是所谓的“哈希值”。

这个哈希值可以根据“哈希函数”的设计,映射到0到桶的大小减一之间的某一个整数。

这样,哈希表就可以把原来的数据,通过哈希值转换为一个范围较小的数,把数据存储到一个有序的桶中,从而大大缩短搜索时间。

哈希表的实现哈希表是使用数组和链表实现的。

数组存放键值对,链表可以解决键值重复的情况,其中每个节点存放着该键值对应的值。

为了更有效的利用存储空间,哈希表有时会采取扩容的方式,即把原来的数组容量翻倍,当存储满的时候就重新分配内存空间,并把原来的数据重新哈希映射到新的桶中。

哈希表的用途哈希表除了作为存储数据的结构,也可以用于排序、缓存、验证数据的完整性等问题。

哈希表常被用来实现快速查找和插入功能,而且它的查找时间复杂度主要取决于所使用的哈希函数,一般在O(1)时间内就可以完成查找。

哈希表也可以快速统计某一个键出现的次数,实现计数排序(Counting Sort)等功能。

哈希表的例题例子1:设计一个哈希表,能够把一个字符串(String)转换为一个哈希值,并且能够用这个哈希值搜索相应的字符串。

解题思路:首先,需要设计一种哈希函数,把一个任意长度的字符串,转换为一个固定长度的哈希值,这里可以采用把字符串中每个字符的ASCII码值相加,再除以字符串长度,取余数的方法。

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。

列车时刻表 c 数据结构设计

列车时刻表 c 数据结构设计

列车时刻表 c 数据结构设计
列车时刻表是一个重要的交通工具信息系统,它用于查
询和展示列车的发车时间、到达时间、车次编号和途经站
点等相关信息。

为了高效地存储和查询时刻表数据,我设
计了以下数据结构。

首先,我们可以使用一个哈希表来存储每个车次的信息。

哈希表的键可以使用车次编号,值则可以是一个包含该列
车所有站点信息的链表。

每个链表节点包括站点名称、到
达时间和发车时间等数据。

此外,我们还需要一个集合来存储所有的站点名称。


样可以方便地进行站点名称的检索和排序。

对于查询功能,我们可以利用哈希表来快速定位到指定
车次,并通过遍历链表获取该车次所有站点的信息。

对于添加新的列车时刻表数据,我们可以根据车次编号
在哈希表中插入一个新的键值对。

如果该车次已存在,则
可以将新的站点信息添加到对应链表中。

同时,我们也需
要将新的站点名称添加到站点名称的集合中。

如果需要删除某个车次的时刻表数据,我们可以在哈希表中定位到指定车次,并删除对应的键值对。

同时,我们也需要从站点名称的集合中删除该车次的所有站点名称。

这样设计的列车时刻表数据结构能够高效地存储和查询列车信息。

它允许快速定位到指定车次,同时可以方便地对车次的站点信息进行添加、删除和修改。

哈工程数据结构实验报告

哈工程数据结构实验报告

哈工程数据结构实验报告一、实验目的本实验的目的是通过对于哈工程的数据结构实验的实践操作,掌握并理解数据结构中的哈希表的基本原理、实现方式,以及相关的查找、插入和删除操作。

通过实验的实践操作,进一步加深对于数据结构的理解和运用能力。

二、实验步骤和实验原理1.实验环境本次实验使用的是C++语言在Visual Studio环境下进行开发。

2.实验内容本次实验主要涉及到哈希表的构建和相关操作的实践。

具体步骤如下:(1)首先创建一个结构体,包括学生姓名和学号等信息。

(2)然后定义哈希表的存储结构,其中包括哈希表的大小、装填因子等。

(3)根据哈希表的大小,创建一个存储结点的数组。

(4)实现哈希函数,根据学生学号计算哈希值。

(5)实现插入操作,即将结点插入到哈希表中的合适位置。

(6)实现查找操作,根据学生学号查找对应的结点。

(7)实现删除操作,根据学生学号删除对应的结点。

(8)测试程序的运行效果,包括对哈希表进行插入、查找和删除操作等。

三、实验结果与分析通过对实验的步骤和原理的实践操作,成功构建了一个哈希表,并实现了插入、查找和删除操作。

在实验结果的分析中,可以发现哈希表具有一定的优势:通过哈希函数的映射,可以将元素快速地插入到对应的位置,从而实现了快速的查找和删除操作。

四、实验总结通过本次实验,我对于哈希表的原理、实现方式以及相关操作有了更深刻的理解。

通过实践操作,我进一步加深了对于数据结构的掌握和运用能力。

同时,我也认识到哈希表在实际应用中的重要性和优势,对于提高数据处理和查询效率有着重要的作用。

期待在日后的学习和工作中能够更加深入地学习和应用数据结构的知识,提升自己的技术水平和能力。

数据结构在程序设计中的应用

数据结构在程序设计中的应用

数据结构在程序设计中的应用概述:在现代的计算机编程领域中,数据结构是一个至关重要的概念。

它是指将数据按照某种特定的方式组织和存储的方法,以便能够高效地操作和管理数据。

数据结构的选择和设计对程序的性能和效率有着深远的影响。

本文将探讨数据结构在程序设计中的应用,并介绍常见的数据结构及其特点。

一、数组(Array)数组是最简单和最基本的数据结构之一。

它是一种线性结构,用于存储相同类型的元素。

数组的特点是可以通过索引快速访问任意位置的元素。

在程序设计中,数组常用于存储有序的数据集合。

例如,在一个学生成绩管理系统中,可以使用数组来存储学生的成绩。

二、链表(Linked List)链表是一种常见的动态数据结构,它由一系列节点组成,每个节点包含数据和指向下一个节点的指针。

链表的特点是插入和删除操作的效率很高,但是访问任意位置的元素的效率较低。

在程序设计中,链表常用于处理频繁插入和删除操作的场景。

例如,在一个任务管理应用中,可以使用链表来实现任务列表。

三、栈(Stack)栈是一种特殊的线性数据结构,遵循先进后出(LIFO)的原则。

栈的特点是只能在栈的一端进行插入和删除操作。

在程序设计中,栈常用于处理递归调用、表达式求值和内存管理等场景。

例如,在一个计算器应用中,可以使用栈来实现表达式的求值过程。

四、队列(Queue)队列是另一种常见的线性数据结构,遵循先进先出(FIFO)的原则。

队列的特点是只允许在队列的一端进行插入操作,在另一端进行删除操作。

在程序设计中,队列常用于处理排队和异步任务处理等场景。

例如,在一个银行系统中,可以使用队列来实现客户排队的过程。

五、树(Tree)树是一种非线性数据结构,它是由一系列节点组成的层次结构。

树的特点是每个节点可以有多个子节点,根节点没有父节点。

在程序设计中,树常用于组织和存储具有层次关系的数据。

例如,在一个文件系统中,可以使用树来表示文件和文件夹之间的关系。

六、图(Graph)图是一种复杂的非线性数据结构,它由一系列节点和节点之间的边组成。

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

一、问题描述针对某个集体(比如你所在的班级)中的“人名”设计一个哈希表,使得平均查找长度均不超过R,完成相应的建表和查表顺序。

二、基本要求假设人名为中国人姓名的汉语拼音形式。

待填入哈希表的人名共有30个,取平均查找长度的上限为2。

哈希函数用除留余数法构造,用伪随机探测再散列法处理冲突。

三、概要设计1.构造结构体:typedef struct{};2.姓名表的初始化:void InitNameTable();3.建立哈希表:void CreateHashTable();4.显示姓名表:void DisplayNameTable();5.姓名查找:void FindName();6.主函数:void main() ;四、详细设计1.姓名表的初始化void InitNameTable(){NameTable[0].py="louyuhong";NameTable[1].py="shenyinghong";NameTable[2].py="wangqi";NameTable[3].py="zhuxiaotong";NameTable[4].py="zhataotao";NameTable[5].py="chenbinjie";NameTable[6].py="chenchaoqun";NameTable[7].py="chencheng";NameTable[8].py="chenjie";NameTable[9].py="chenweida";NameTable[10].py="shanjianfeng";NameTable[11].py="fangyixin";NameTable[12].py="houfeng";NameTable[13].py="hujiaming";NameTable[14].py="huangjiaju";NameTable[15].py="huanqingsong";NameTable[16].py="jianghe";NameTable[17].py="jinleicheng";NameTable[18].py="libiao";NameTable[19].py="liqi";NameTable[20].py="lirenhua";NameTable[21].py="liukai";NameTable[22].py="louhanglin";NameTable[23].py="luchaoming";NameTable[24].py="luqiuwei";NameTable[25].py="panhaijian";NameTable[26].py="shuxiang";NameTable[27].py="suxiaolei";NameTable[28].py="sunyubo";NameTable[29].py="wangwei";for (i=0;i<NAME_LEN;i++) //将字符串的各个字符所对应的ASCII码相加,所得的整数做为哈希表的关键字{int s=0;char *p=NameTable[i].py;for (j=0;*(p+j)!='\0';j++)s+=toascii(*(p+j));NameTable[i].m=s;}}2.建立哈希表void CreateHashTable(){for(i=0;i<HASH_LEN;i++){HashTable[i].py="\0";HashTable[i].m =0;HashTable[i].si=0;}for(i=0;i<NAME_LEN;i++){int sum=1,j=0;int adr=(NameTable[i].m)%P; //除留余数法 H(key)=key MOD p,p<=mif(HashTable[adr].si==0) //如果不冲突,将姓名表赋值给哈希表{HashTable[adr].m =NameTable[i].m;HashTable[adr].py=NameTable[i].py;HashTable[adr].si=1;}else / /如果冲突{while(HashTable[adr].si!=0){adr=(adr+d[j++])%HASH_LEN;//伪随机探测再散列法处理冲突sum=sum+1;//查找次数加1}HashTable[adr].m =NameTable[i].m; //将姓名表复制给哈希表对应的位置上HashTable[adr].py=NameTable[i].py;HashTable[adr].si=sum;}}}3.显示姓名表与哈希表void DisplayNameTable(){printf("\n地址 \t\t 姓名 \t\t 关键字\n");for (i=0;i<NAME_LEN;i++)printf("%2d %18s\t\t %d \n",i,NameTable[i].py,NameTable[i].m);}void DisplayHashTable(){float asl=0.0;printf("\n\n 地址 \t\t 姓名 \t\t 关键字 \t 搜索长度\n"); //显示的格式for (i=0;i<HASH_LEN;i++){printf("%2d %18s \t\t %d\t\t %d\n",i,HashTable[i].py,HashTable[i].m,HashTable[i].si);asl+=HashTable[i].si;}asl/=NAME_LEN; //求得ASLprintf("\n\n平均查找长度:ASL(%d)=%f \n",NAME_LEN,asl);}4.姓名查找void FindName(){char name[20]={0};int s=0,sum=1,adr;printf("\n请输入想要查找的姓名的拼音:");scanf("%s",name);for (j=0;j<20;j++) //求出姓名的拼音所对应的ASCII作为关键字s+=toascii(name[j]);adr=s%P; //除留余数法j=0;if(HashTable[adr].m==s&&!strcmp(HashTable[adr].py,name)) //分3种情况进行判断,并输出超找结果printf("\n姓名:%s 关键字:%d 查找长度为:1\n",HashTable[adr].py,s);else if (HashTable[adr].m==0)printf("没有想要查找的人!\n");else{while(1){adr=(adr+d[j++])%HASH_LEN; //伪随机探测再散列法处理冲突sum=sum+1;//查找次数加1if(HashTable[adr].m==0){printf("没有想要查找的人!\n");break;}if(HashTable[adr].m==s&&!strcmp(HashTabl e[adr].py,name)){printf("\n姓名:%s 关键字:%d 查找长度为:%d\n",HashTable[adr].py,s,sum);break;}}}}五、测试结果六、实验环境C-Free七、源程序代码#include<stdio.h>#include<time.h> //time用到的头文件#include<stdlib.h> //随机数用到的头文件#include<ctype.h> //toascii()用到的头文件#include<string.h> //查找姓名时比较用的头文件#define HASH_LEN 50 //哈希表的长度#define P 47 //小于哈希表长度的P #define NAME_LEN 30 //姓名表的长度typedef struct //姓名表{char *py; //名字的拼音int m; //拼音所对应的}NAME;NAME NameTable[HASH_LEN]; //全局定义姓名表typedef struct //哈希表{char *py; //名字的拼音int m; //拼音所对应的ASCII总和int si; //查找长度}HASH;HASH HashTable[HASH_LEN]; //全局定义哈希表int d[30],i,j; //全局定义随机数,循环用的i、jvoid InitNameTable() //姓名表的初始化{NameTable[0].py="louyuhong";NameTable[1].py="shenyinghong";NameTable[2].py="wangqi";NameTable[3].py="zhuxiaotong";NameTable[4].py="zhataotao";NameTable[5].py="chenbinjie";NameTable[6].py="chenchaoqun";NameTable[7].py="chencheng";NameTable[8].py="chenjie";NameTable[9].py="chenweida";NameTable[10].py="shanjianfeng";NameTable[11].py="fangyixin";NameTable[12].py="houfeng";NameTable[13].py="hujiaming";NameTable[14].py="huangjiaju";NameTable[15].py="huanqingsong";NameTable[16].py="jianghe";NameTable[17].py="jinleicheng";NameTable[18].py="libiao";NameTable[19].py="liqi";NameTable[20].py="lirenhua";NameTable[21].py="liukai";NameTable[22].py="louhanglin";NameTable[23].py="luchaoming";NameTable[24].py="luqiuwei";NameTable[25].py="panhaijian";NameTable[26].py="shuxiang";NameTable[27].py="suxiaolei";NameTable[28].py="sunyubo";NameTable[29].py="wangwei";for (i=0;i<NAME_LEN;i++) //将字符串的各个字符所对应的ASCII码相加,所得的整数做为哈希表的关键字{int s=0;char *p=NameTable[i].py;for (j=0;*(p+j)!='\0';j++)s+=toascii(*(p+j));NameTable[i].m=s;}}void CreateHashTable() //建立哈希表{for(i=0;i<HASH_LEN;i++){HashTable[i].py="\0";HashTable[i].m =0;HashTable[i].si=0;for(i=0;i<NAME_LEN;i++){int sum=1,j=0;int adr=(NameTable[i].m)%P; //除留余数法 H(key)=key MOD p,p<=mif(HashTable[adr].si==0) //如果不冲突,将姓名表赋值给哈希表{HashTable[adr].m =NameTable[i].m;HashTable[adr].py=NameTable[i].py;HashTable[adr].si=1;}else //如果冲突{while(HashTable[adr].si!=0){adr=(adr+d[j++])%HASH_LEN; //伪随机探测再散列法处理冲突sum=sum+1; //查找次数加1}HashTable[adr].m =NameTable[i].m; //将姓名表复制给哈希表对应的位置上HashTable[adr].py=NameTable[i].py;HashTable[adr].si=sum;}}void DisplayNameTable() //显示姓名表{printf("\n地址 \t\t 姓名 \t\t 关键字\n");for (i=0;i<NAME_LEN;i++)printf("%2d %18s \t\t %d \n",i,NameTable[i].py,NameTable[i].m);}void DisplayHashTable() // 显示哈希表{float asl=0.0;printf("\n\n 地址 \t\t 姓名 \t\t 关键字 \t 搜索长度\n"); //显示的格式 for (i=0;i<HASH_LEN;i++){printf("%2d %18s \t\t %d\t\t %d\n",i,HashTable[i].py,HashTable[i].m,HashTable[i].si);asl+=HashTable[i].si;}asl/=NAME_LEN; //求得ASLprintf("\n\n平均查找长度:ASL(%d)=%f \n",NAME_LEN,asl);}void FindName() //查找{char name[20]={0};int s=0,sum=1,adr;printf("\n请输入想要查找的姓名的拼音:");scanf("%s",name);for (j=0;j<20;j++) //求出姓名的拼音所对应的ASCII作为关键字s+=toascii(name[j]);adr=s%P; //除留余数法j=0;if(HashTable[adr].m==s&&!strcmp(HashTable[adr].py,name)) //分3种情况进行判断,并输出超找结果printf("\n姓名:%s 关键字:%d 查找长度为: 1\n",HashTable[adr].py,s);else if (HashTable[adr].m==0)printf("没有想要查找的人!\n");else{while(1){adr=(adr+d[j++])%HASH_LEN; //伪随机探测再散列法处理冲突sum=sum+1; //查找次数加1if(HashTable[adr].m==0){printf("没有想要查找的人!\n");break;}if(HashTable[adr].m==s&&!strcmp(HashTable[adr].py,name)){printf("\n姓名:%s 关键字:%d 查找长度为:%d\n",HashTable[adr].py,s,sum);break;}}}}int main() //主函数{char a;srand((int)time(0));for(i=0;i<30;i++) //用随机函数求得伪随机数列d[i](在1到50之间)d[i]=1+(int)(HASH_LEN*rand()/(RAND_MAX+1.0));InitNameTable();CreateHashTable();puts(" 哈希表设计");//显示菜单栏start:puts("\n*----------------------------菜单栏------------------------------*");puts(" \t\t\t 1. 显示姓名表");puts(" \t\t\t 2. 显示哈希表");puts(" \t\t\t 3. 查找");puts(" \t\t\t 4. 退出 ");puts("*----------------------------------------------------------------*");restart:printf("\n\t请选择:");scanf("%s",&a);switch(a) //根据选择进行判断,直到选择退出时才可以退出 {case '1':DisplayNameTable();break;case '2':DisplayHashTable();break;case '3':FindName();break;case '4':exit(0);break;default:printf("\n请输入正确的选择!\n");goto restart;}goto start;}。

相关文档
最新文档