哈希表实验报告(20200623044247)

合集下载

哈希实验报告

哈希实验报告

一、 问题描述1. 实验题目:利用哈希表统计两源程序的相似性2. 基本要求:1)内容: 对于两个 C 语言的源程序清单,用哈希表的方法分别统计两程序中使用C 语言关键字的情况,并最终按定量的计算结果,得出两份源程序的相似性。

2)要求与提示:C 语言关键字的哈希表可以自建,也可以采用下面的哈希函数作为参考: Hash(key)=(key 第一个字符序号*100+key 最后一个字符序号)%41表长m 取43。

此题的工作主要是扫描给定的源程序,累计在每个源程序中C 语言关键字出现的频度。

为保证查找效率,建议自建哈希表的平均查找长度不大于2。

扫描两个源程序所统计的所有关键字不同频度, 可以得到两个向量。

如下面简单的例子所示:根据程序1和程序2中关键字出现的频度,可提取到两个程序的特征向量X1和X2,其中 X1=(4 3 0 4 3 0 7 0 0 2)TX2=(4 2 0 5 4 0 5 2 0 1)T一般情况下,可以通过计算向量Xi 和Xj 的相似值来判断对应两个程序的相似性,相似值的判别函数计算公式为: ji Ti j i X X X X X S ⋅=)(,其中,i T i X X X ⋅=。

S(X i ,X j )的值介于[0,1]之间,也称广义余弦,即S(X i ,X j )=COSθ。

X i =X j 时,显见S(X i ,X j )=1,θ=0;X i X j 差别很大时,S(X i ,X j )接近0,θ接近π/2。

如X1=(1 0)T,X2=(0 1)T,则S(X i ,X j )=0,θ=π/2。

当S 值接近1 的时候,为避免误判相似性(可能是夹角很小,模值很大的向量),应当再次计算之间的“几何距离” D(X i ,X k )。

其计算公式为:)()(),(k i Tk i k i j i X X X X X X X X D --=-= 最后的相似性判别计算可分两步完成:第一步 用式(3-1)计算S ,把接近 1的保留,抛弃接近0的情况(把不相似的排除); 第二步 对保留下来的特征向量,再用式(3-2)计算D ,如D 值也比较小,说明两者对应的程序确实可能相似(慎重肯定相似的)。

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

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

//头文件main.c#include<stdio.h>#include<stdlib.h>struct keyNum* hash[100];struct keyNum* insertHash(struct keyNum*,int);//关键字插入链表int searchHash(struct keyNum*,int m);//查找链表中是否存在值为m的整数void print(struct keyNum*);//打印链表struct keyNum{int key;//关键字struct keyNum *next;};void main(){int i,k,m,n,num,flag,l,j;int a[] = {280,700,603,430,641,907,640};struct keyNum *head = NULL;num = sizeof(a)/sizeof(int);for(i=0;i<sizeof(a)/sizeof(int);i++){k = a[i];m=k%(num+1);//计算得到关键字的哈希值hash[m]=insertHash(hash[m],k);//将关键字k插入到哈希值为m的链表中}printf("采用链地址法得到的哈希表为:\n");for(i=0;i<num+1;i++){printf("第%d行:",i);print(hash[i]);printf("\n");}printf("请输入要查找的整数值:\n");scanf("%d",&n);for(i=0;i<num+1;i++){l=searchHash(hash[i],n);if(l==1){j=i;break;}}if(l==1)printf("整数值%d在哈希表中,位置为链表%d\n",n,j);}struct keyNum * insertHash(struct keyNum*head,int m){struct keyNum *p0,*p1,*p2,*temp;temp=(struct keyNum*)malloc(sizeof(struct keyNum));temp->key=m;p1=head;p0=temp;//要插入的节点(值为m);if(head==NULL)//1,原来的链表为空,插入到head后{head=p0;p0->next=NULL;}else//原来的链表不为空{while((p0->key>p1->key)&&(p1->next!=NULL))//移动到适当位置 {p2=p1;p1=p1->next;}if(p0->key<=p1->key){if(head==p1)head=p0;//2,插入到第一个节点之前else p2->next=p0;//3,插入到p2指向的节点之后p0->next=p1;}else//4,插入到结尾处{p1->next=p0;p0->next=NULL;}}return(head);}int searchHash(struct keyNum*head,int m)//查找链表head中是否存在m {int k=0;struct keyNum*p;p=head;if(head!=NULL)do{if(p->key==m) //存在m{k=1;break;}p=p->next;}while(p!=NULL);return(k);//存在m值则返回1,否则返回0;}void print(struct keyNum*head)//打印链表head {struct keyNum*p;p=head;if(head!=NULL){do{printf(" -> %d ",p->key);p=p->next;}while(p!=NULL);}elseprintf("null");}头文件HashTable.htypedef struct KeyNum{int key;struct KeyNum* next;}keyNum;//插入keyNum* insertHash(keyNum* head,int m){keyNum *p0,*p1,*p2,*temp;temp=(keyNum*)malloc(sizeof(keyNum));temp->key=m;p1=head;p0=temp;//要插入的节点(值为m);if(head==NULL)//1,原来的链表为空,插入到head后{head=p0;p0->next=NULL;}else//原来的链表不为空{while((p0->key>p1->key)&&(p1->next!=NULL))//移动到适当位置 {p2=p1;p1=p1->next;}if(p0->key<=p1->key){if(head==p1)head=p0;//2,插入到第一个节点之前else p2->next=p0;//3,插入到p2指向的节点之后p0->next=p1;}else//4,插入到结尾处{p1->next=p0;p0->next=NULL;}}return(head);}//查找int searchHash(keyNum*head,int m)//查找链表head中是否存在m{int k=0;keyNum*p;p=head;if(head!=NULL)do{if(p->key==m) //存在m{k=1;break;}p=p->next;}while(p!=NULL);return(k);//存在m值则返回1,否则返回0;}void print(keyNum* head)//打印链表head{keyNum*p;p = head;if(head!=NULL){do{printf(" -> %d ",p->key);p=p->next;}while(p!=NULL);}elseprintf("null");}测试程序 Main.c#include<stdio.h>#include<stdlib.h>#define mSize 100 //数组最大个数#include "HashTable.h"void main(){int i,k,m,n,num,l,j;int a[] = {180,750,600,430,541,900,640};keyNum* hash[mSize];keyNum* head = NULL;num = sizeof(a)/sizeof(int);for(i=0;i<num+1;i++)hash[i] = NULL;for(i = 0;i<num;i++){k = a[i];m=k%(num+1);//计算得到关键字的哈希值hash[m] = insertHash(hash[m],k);//将关键字k插入到哈希值为m 的链表中}printf("当前哈希表如下:\n");for(i=0;i<num+1;i++){printf("第%d行:",i);print(hash[i]);printf("\n");}printf("\n");printf("请输入要查找的元素:\n");scanf("%d",&n);for(i=0;i<num+1;i++){l=searchHash(hash[i],n);if(l==1){j=i;break;}}if(l==1)printf("\n整数值%d在哈希表中,位置为链表%d\n",n,j);else printf("\n整数值%d不在哈希表中!\n");}。

哈希实验报告

哈希实验报告

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

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

正文内容:一、二次探测法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. 哈希函数的选择:根据关键字的特性选择适合的哈希函数,将关键字映射到哈希表的存储位置。

3. 插入操作:将关键字通过哈希函数计算得到索引位置,如果该位置为空,则直接插入;如果该位置已存在关键字,则发生冲突,需要解决冲突。

4. 冲突解决:常见的冲突解决方法包括线性探测、二次探测和链地址法等。

5. 查找操作:通过哈希函数计算得到关键字的索引位置,进行查找操作。

如果该位置为空,则表示查找失败;如果该位置不为空,则继续比较关键字是否相等。

6. 删除操作:将关键字标记为删除状态,或将该位置置为空。

三:实验步骤本实验中,我们以哈希表实现哈希查找算法,具体步骤如下: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)进行查找,先计算要生成字符串的地址,再到散列表中进行查找比较。

哈希表报告

哈希表报告

哈希表设计题目哈希表设计[问题描述]针对自己的班集体中的“人名”设计一个哈希表,使得平均查找长度不超过R,完成相应的建表和查表程序。

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

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

构造哈希函数,用链表法处理冲突。

[测试数据]读取熟悉的30个人的姓名作测试。

一.需求分析:1. 针对自己的班集体中的“人名”设计一个哈希表,使得平均查找长度不超过R,完成相应的建表和查表程序。

2. 人名为中国姓名的汉语拼音形式。

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

3. 用每个名字各个字符所对应的ASCII码相加,所得的整数做为哈希表的关键字,用除余法构造哈希函数,用拉链法处理冲突。

4.输入数据:zhaoxuening ,muchunyang ,lvzhihui,jiangbiwen,zhangye ,libaoling,yulin,wangjie,huangzheng,xiahaiyun,tanyongli,yangjiaqi,liufengbin,wangfeng,huangweilun,chenliang,hezhicong,yaochengzhong,chaozhihao,wangshipeng,ganyongze,luyang,baichongliang,zhurui,chenyiming,pengxuan,equanming,lishiwei,baitian,wuliao。

5.测试数据:lishiwei,zhurui,abcdefg,wangshipeng二.概要设计1.程序流程图2.存储结构:名字表:struct Name{ //名字表char *name; //名字int key; //关键码}哈希表:struct Node;typedef struct Node * PNode;struct Node{ //每条单链表结点结构定义char *name;PNode link;};struct HashDic{ //哈希表结构定义PNode llist[P]; //哈希表所包含的单链表,P为基本区域长度float search; //总查找长度float total; //哈希表中名字数int m; //哈希表长度};};typedef struct HashDic *PHashDic; //哈希表类型3.主要算法: (1). int h(char *py){ }//除余法,返回名字在哈希表中的相应地址(2) PHashDic create_EmptyDic(){ } //创建空哈希表(3)void insert_node(PHashDic phash,char *py) { } //插入算法(4)void search_node(PHashDic phash){ } //查找算法(5)void delete_node(PHashDic phash){ } //删除算法(6)void output_name(){ } //输出姓名表(7)void output_hash(PHashDic phd){ } //输出哈希表(8)void InitNameTable(){ } //姓名表的初始化(9)void print(){ } //打印操作菜单(10)void main(){ } //主函数三.详细设计1. 除余法,返回名字在哈希表中的相应地址int h(char *py){int key;for (int i=0;i<NAME_LEN;i++) //将字符串的各个字符所对应的ASCII码相加,所得的整数做为名字的关键字{int s=0;char *p=py;for (int j=0;*(p+j)!='\0';j++)s+=int(*(p+j));key=s;}return key%P;}2. 创建空哈希表PHashDic create_EmptyDic(){PHashDic phash=(PHashDic)malloc(sizeof(struct HashDic));int i;phash->search=0;phash->total=0;phash->m=P;for(i=0;i<phash->m;i++){phash->llist[i]=NULL;}return phash;}3. 插入算法void insert_node(PHashDic phash,char *py){PNode p,q;int r=1; //查找长度大于2的py的查找长度nt adr=h(py);if(phash->llist[adr]==NULL){ //如果单链表为空,向单链表插入第一个元素p=(PNode)malloc(sizeof(struct Node)); //创建新结点p->name=py;p->link=NULL;phash->llist[adr]=p;phash->total++;phash->search+=1;return;}q=phash->llist[adr];if (strcmp(q->name,py)==0) //如果已有此元素则不再插入{cout<<"名字已经存在"<<endl;return;}while (q->link!=NULL){if(strcmp(q->link->name,py==0{cout<<"名字已经存在"<<endl;return;}q=q->link;r++;}p=(PNode)malloc(sizeof(struct Node)); //否则就插入单链表最后p->name=py;p->link=NULL;q->link=p;r++;phash->search+=r;phash->total++;}4. 查找算法void search_node(PHashDic phash){PNode p;int adr,r; //哈希表地址和查找长度char py[20];cout<<"请输入要查找的名字:\n";cin>>py;adr=h(py);if(phash->llist[adr]==NULL) cout<<"查找结果:\n"<<"没有想要查找的人!!\n";//如果相应单链表为空,则没有所要查找的名字else {p=phash->llist[adr];while(strcmp(p->name,py)!=0 && p->link!=NULL)//否则对比单链表内容直到查找到名字或对比完单链表中数据{p=p->link;r++;}if(strcmp(p->name,py)==0)cout<<"查找结果:\n"<<"名字:"<<py<<" 地址"<<adr<<" 查找长度"<<r<<endl;//查找到名字else cout<<"查找结果:\n"<<"没有想要查找的人\n"; //对比完单链表中数据,没有该名字}}5. 删除算法void delete_node(PHashDic phash){PNode p,q;int r=1; //查找长度char py[20]={0};cout<<"请输入要删除的名字:\n";cin>>py;int adr=h(py);if(phash->llist[adr]==NULL) //如果相应单链表为空,则没有所要删除的名字{cout<<"没有想要删除的名字!!\n";return;}p=phash->llist[adr];if(strcmp(p->name,py)==0) //如果要删除的是单链表第一个元素{phash->llist[adr]=p->link;free(p);cout<<"删除完成!!\n";phash->total--;phash->search-=1;return;}while(p->link!=NULL && strcmp(p->link->name,py)!=0 )//否则对比单链表内容直到查找到名字或对比完单链表中数据{p=p->link;}if(strcmp(p->link->name,py)==0) //查找到名字{q=p->link;p->link=q->link;free(q);cout<<"删除完成!!\n";r++;phash->search-=r;phash->total--;return;}else //对比完单链表中数据,没有该名字{cout<<"没有想要删除的名字!!\n";return;}}6. //输出姓名表void output_name(){ //输出姓名表int i;printf("序号\t\t 姓名\t\t 关键字\n");for (i=0;i<NAME_LEN;i++)printf("%2d %18s \t\t %d \n",i,NameTable[i].name,NameTable[i].key); }7.输出哈希表void output_hash(PHashDic phd){ //输出哈希表PNode p;float ASL; //平均查找长度nt i;cout<<"地址名字\n";for (i=0;i<P;i++){p=phd->llist[i];cout<<i;while(p!=NULL){cout<<" 一> "<<p->name;p=p->link;}cout<<endl;}ASL=phd->search/phd->total;cout<<"平均查找长度:"<<ASL<<endl;}8. 姓名表的初始化void InitNameTable(){NameTable[0].name="zhaoxuening";NameTable[1].name="muchunyang";NameTable[2].name="lvzhihui";NameTable[3].name="jiangbiwen";NameTable[4].name="zhangye";NameTable[5].name="libaoling";NameTable[6].name="yulin";NameTable[7].name="wangjie";NameTable[8].name="huangzheng";NameTable[9].name="xiahaiyun";NameTable[10].name="tanyongli";NameTable[11].name="yangjiaqi";NameTable[12].name="liufengbin";NameTable[13].name="wangfeng";NameTable[14].name="huangweilun";NameTable[15].name="chenliang";NameTable[16].name="hezhicong";NameTable[17].name="yaochengzhong";NameTable[18].name="chaozhihao";NameTable[19].name="wangshipeng";NameTable[20].name="ganyongze";NameTable[21].name="luyang";NameTable[22].name="baichongliang";NameTable[23].name="zhurui";NameTable[24].name="chenyiming";NameTable[25].name="pengxuan";NameTable[26].name="equanming";NameTable[27].name="lishiwei";NameTable[28].name="baitian";NameTable[29].name="wuliao";for (int i=0;i<NAME_LEN;i++)//将字符串的各个字符所对应的ASCII码相加,所得的整数做为名字的关键字{int s=0;for (int j=0;NameTable[i].name[j]!='\0';j++)s+=int(NameTable[i].name[j]);NameTable[i].key=s;}}9. 打印操作菜单void print(){cout<<" ********************************************************\n";cout<<" 操作菜单\n";cout<<" 1.输出姓名表\n";cout<<" 2.输出哈希表\n";cout<<" 3.查找\n";cout<<" 4.删除\n";cout<<" 5.插入\n";cout<<" 6.退出\n";cout<<" ********************************************************\n"; }10.主函数void main(){int i,c,k=0;PHashDic phash=create_EmptyDic(); //创建空哈希表phashInitNameTable();for (i=0;i<NAME_LEN;i++) //将名字表中的名字存入哈希表insert_node(phash,NameTable[i].name);print(); //打印操作菜单cout<<"请选择操作:";cin>>c;while(c!=1&&c!=2&&c!=3&&c!=4&&c!=5&&c!=6) {cout<<"请重新选择操作:";cin>>c;}do{//当选择6时结束算法,选择1,2,3,4,5则执行相应操作直到结束switch(c){case 1:output_name();print();break; //输出姓名表case 2: output_hash(phash);print();break; //输出哈希表case 3:search_node(phash);print();break; //查找case 4:delete_node(phash);print();break; //删除case 5:{char py[20]; //插入cout<<"请输入要插入的名字:\n";cin>>py;insert_node(phash,py);}print();break;case 6:cout<<"已退出\n";break;default:cout<<"\n请输入正确的选择!\n:";}if(c!=6){cout<<"请选择操作:";cin>>c;while(c!=1&&c!=2&&c!=3&&c!=4&&c!=5&&c!=6){cout<<"请重新选择操作:";cin>>c;}}}while (c==1||c==2||c==3||c==4||c==5); }四.调试分析1.输出姓名表2.输出哈希表3.查找:lishiwei和abcdefg4.删除:lishiwei,zhurui,abcdefg5.插入:abcdefg和wangshipeng6.退出五.课程设计总结算法分析及改进:1. 由于要对哈希表进行插入,删除等操作字典元素处于动态,而且名字出现无规律可言,因此采用除余法构造哈希函数h(x) = x mod P 。

哈希表实验报告

哈希表实验报告

数据结构实验报告四——哈希表查找名字(字符串)实验题目:哈希表查找名字(字符串)实验目标:输入一组名字(至少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具体值由宏定义决定)。

哈希表实验报告

哈希表实验报告

实习报告题目:设计一个哈希表,完成相应的建表和查表程序一、班级:1503013 姓名:李睿元学号:完成日期:需求分析1. 假设人名为中国人名的汉语拼音形式;2. 待填入哈希表的姓名共有30个,去平均查找长度的上限为2;3. 哈希函数用除留余数法构造,用伪随机探测再散列法处理冲突;4. 取读者周围较熟悉的30个人的姓名。

二、概要设计1. 抽象数据类型的定义:(1)人名数据表:typedef struct Node{char name[20];int key;}Node,NodeList[MAX];(2)哈希表:typedef struct hashtable{char* name;int key;int conflict_time;}HashTable[hashlen];(3)变量:#define P 61主要函数的实现:(1)哈希函数:int Hash(int key)(2)关键字获得:int GetKey(char str[])(3)文件流中读取姓名:void GetName(NodeList &L,int i,FILE* fp)(4)哈希表的初始化:void InitialHashTable(HashTable &ht)(5)伪随机探测序列的生成:void CreatConfilctArray(int n[])(6)哈希表的生成:void CreatHashTable(HashTable &ht,NodeList L,int* n)(7)哈希表的查询:void SearchHashTable(HashTable ht,int* n,char get_name[])三、详细设计#include <>#include <>#include <>#define P 61ame);L[i].key=GetKey(L[i].name); */fscanf(fp,"%s",L[i].name);L[i].key=GetKey(L[i].name);onflict_time=0;ht[n].name=NULL;ht[n].key=0;n++;}}void CreatConfilctArray(int n[]){ey);if(ht[t].conflict_time==0){ht[t].name=L[i].name;ht[t].conflict_time++;ht[t].key=L[i].key;printf("姓名:%s key值:%d 表内存储位置:%d\n",L[i].name,L[i].key,t);}else{int m=0;int d=(t+n[m])%hashlen;while(ht[d].conflict_time!=0){ht[d].conflict_time++;m++;d=(t+n[m])%hashlen;}ht[d].name=L[i].name;ht[d].conflict_time++;ht[d].key=L[i].key;printf("姓名:%s key值:%d 表内存储位置:%d\n",L[i].name,L[i].key,d);}i++;}}void SearchHashTable(HashTable ht,int* n,char get_name[]){onflict_time==0&&ht[h].key!=k){printf("表中未找到无此人!\n");break;}else if(ht[h].key==k){printf("已找到%s,表内存储位置:%d\n",get_name,h);break;}else{p++;h=n[p];}*/if(ht[h].name==NULL){printf("表中未找到无此人!\n");break;}else if(strcmp(ht[h].name,get_name)==0){printf("已找到%s,表内存储位置:%d,查找次数:%d\n",get_name,h,s_time);break;}else{p++;h=(t+n[p])%hashlen;s_time++;}}}int main(){哈希表可以在理想情况下不经过任何比较,一次存取就能得到所查记录;2. 除留余数法对于p的选择很重要,经过分析后的选择是p为小于等于m的最大素数,最终选择了61;3. 伪随机探测再散列相较于线性探测再散列或二次探测再散能有效的防止二次堆积。

哈希表(实验报告附C++源码)

哈希表(实验报告附C++源码)

散列表一、问题描述我们希望在浩瀚的图书中,去发现一本书是否存在。

我们不知道书的编号,只知道它的书名。

(其实这已经不错了...)。

通过书名,来查询它是否存在。

为了简化问题,我们假设每本书的书名都是一组小写字母组成,长度不超过100字符。

二、需求分析1.根据输入建立图书名称表,采用散列表实现该表,散列函数自建。

2.数据的输入输出格式:输入分为两部分输入:第一部分,第一行是行数n,n <= 5000。

余下n行,每行一个字符串。

表示已存在的图书记录。

第二部分,第一行是行数m,m <= 1000。

余下m行,每行一个字符串。

表示要查询的图书记录。

输出:输出为m行,如果被查的记录存在,则输出"YES",如果不存在则输出"NO"。

3.测试数据输入:4aansandhellocpp9abanasansandandehellocbbhellocpp输出:YESNONONOYESYESNONOYES三、概要设计抽象数据类型class Node//最基本的抽象数据类型{public:char ch[20];//链表中,记录表中数据,20为查找字符串的长度Node* next;//指向下一个结点Node(const char* in);//构造函数};class List{ //用Node作结点的链表public:Node* head;Node* tail;Node* fence;List();~List();bool append(const char* in);//像链表中,增添结点};class Hash//哈希表的详细设计{private:List* myList;//指向链表数组public:int getSubInt(const char* in) const; //哈希函数,把传进的字符串的ASCII//相加,再mod哈西表大小,得该字符串的位置Hash();~Hash();bool insert(const char*) const;//建立哈希表bool find(const char*) const;//在哈希表中查找};int Hash::getSubInt(const char *in) const//哈希函数的实现{int sum=0,i=0;while(in[i]!='\0')sum+=in[i++];return sum%tableSize;}算法的基本思想本程序采用了开散列表,用一个链表数组实现。

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

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

数据结构课程设计哈希表实验报告数据结构课程设计哈希表实验报告福建工程学院课程设计课程:算法与数据结构题目:哈希表专业:网络工程班级: xxxxxx班座号: xxxxxxxxxxxx姓名: xxxxxxx12 月 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) //冲突处理函数,采用二次探测再散列法解决冲突{。

《哈希表》项目实验报告

《哈希表》项目实验报告

《哈希表》项目实验报告1、实验名称哈希表问题2、小组成员刘艳宁、邓芳益;3、主要内容和步骤:(1)分析问题描述,明确问题目标对于一个哈希表,它是通过哈希算法,然后将数据按照哈希算法所得到的哈希地址存入到哈希表中。

所以对于一个哈希表,要了解它的存储方式、哈希表的冲突处理、数据的输入、数据的追加、哈希表的判空、哈希表清空、数据的查找(2)分析问题数据描述[数据描述]首先分析哈希表的构造方法:除留余数法取关键字被某个不大于哈希表表长m的数p除后所得余数为哈希地址。

H(key)=key MOD p (p<=m);//哈希表的存储方法但是由于java中已经嵌入了哈希表,所以直接调用java中的哈希表:Import java.uilt.HashMap//调用java中的哈希表函数;(3)确定算法思路,准确描述算法[算法描述]首先运用java里面的哈希表;import java.util.Scanner;//调用java里面的Scanner供用户进行数据的输入import java.util.HashMap;//调用java哈希表根据公式:H(key)=key MOD p (p<=m)用输入的关键字来与哈希表的总长度来进行求余运算,然后将求得的余数存入到哈希表相应的位置中对于哈希表的查找:则根据哈希表的除留余数法然后进行数据的查找;当ASL为1时时最理想的,因为只需要查找一次,如果第一次没有查找到,则在先前的位置上加一进行查找,直到查找到数据为止然后返回。

(4)运行数据记录输入:学号:1000 姓名:张三输入:学号:1001 姓名:李四输出哈希表数据,然后进行判空,查找等操作(5)实验效果图示4、实验总结:(心得体会、处理结果、存在的问题、建议和意见等)心得体会:如果要实现哈希表的各个操作,首先要了解哈希表的存储方式;其次就是算法的构造上面,该程序是直接调用java中的hashmap,所以在算法上程序构造相对的比较简单。

哈希表的实验报告

哈希表的实验报告

哈希表的实验报告哈希表的实验报告哈希表是一种常见的数据结构,用于存储和查找数据。

在本次实验中,我们将探索哈希表的原理、实现和性能,并通过实验验证其效果。

一、实验目的本次实验的目的是探索哈希表的原理和实现方法,并通过实验测试不同哈希函数和哈希表大小对性能的影响。

二、实验原理哈希表是一种基于哈希函数的数据结构,它将数据存储在数组中,通过哈希函数将数据映射到数组的特定位置。

哈希函数将数据转换为数组的索引,使得数据可以快速存储和查找。

哈希函数的选择很重要,一个好的哈希函数应该具备以下特点:1. 均匀性:哈希函数应该将数据均匀地分布到不同的索引位置,以避免冲突。

2. 高效性:哈希函数应该具有高效的计算速度,以提高哈希表的性能。

3. 低冲突:哈希函数应该尽可能减少冲突的发生,以提高哈希表的查找效率。

三、实验方法1. 实现哈希表:我们首先需要实现一个基本的哈希表数据结构。

哈希表可以使用数组来存储数据,每个数组元素称为一个桶,每个桶可以存储多个数据项。

在实现哈希表时,我们需要考虑如何处理冲突,常见的方法有链地址法和开放地址法。

2. 实现哈希函数:我们需要实现不同的哈希函数,以测试它们的性能。

常见的哈希函数包括除余法、乘法和平方取中法等。

我们可以通过实验比较它们的性能,选择最合适的哈希函数。

3. 测试性能:我们需要设计一系列实验,测试不同哈希函数和哈希表大小对性能的影响。

可以通过插入、查找和删除等操作来评估哈希表的性能。

我们可以记录每个操作的平均时间复杂度和空间占用情况,并绘制图表来展示结果。

四、实验结果与分析通过实验,我们得到了不同哈希函数和哈希表大小下的性能数据。

我们可以观察到不同哈希函数对性能的影响,并选择最优的哈希函数。

同时,我们还可以观察到哈希表大小对性能的影响,选择合适的哈希表大小以平衡性能和空间占用。

五、实验总结本次实验我们深入了解了哈希表的原理和实现方法,并通过实验验证了不同哈希函数和哈希表大小对性能的影响。

实验5 哈希表实验报告

实验5    哈希表实验报告

哈希表一、实验目的学会哈希函数的构造方法,处理冲突的机制以及哈希表的查找。

二、实验内容说明以下概念1、哈希函数在一般情况下,需在关键字与记录在表中的存储位置之间建立一个函数关系,以f(key) 作为关键字为key 的记录在表中的位置,通常称这个函数f(key) 为哈希函数。

1) 哈希函数是一个映象,即:将关键字的集合映射到某个地址集合上,它的设置很灵活,只要这个地址集合的大小不超出允许范围即可;2) 由于哈希函数是一个压缩映象,因此,在一般情况下,很容易产生“冲突”现象,即:key1≠ key2,而f(key1) = f(key2)。

2、哈希表根据设定的哈希函数f(key)和处理冲突的方法将一组关键字映像到一个有限的连续的地址集(区间)上,并以关键字在地址集中的“像”作为记录在表中的存储位置,这种表便称为哈希表,这一映像过程称为哈希造表或散列,所得存储位置称哈希地址或散列地址。

3、冲突及处理1)冲突:对不同的关键字可能得到同意哈希地址,即key1≠ key2,而f(key1) = f(key2),这种现象称冲突(collision)。

2)处理方法:开放地址法。

4、哈希表的查找分析从查找过程得知,哈希表查找的平均查找长度实际上并不等于零。

决定哈希表查找的ASL 的因素:1) 选用的哈希函数;2) 选用的处理冲突的方法;3) 哈希表饱和的程度,装载因子 α=n/m 值的大小(n —记录数,m —表的长度)一般情况下,可以认为选用的哈希函数是“均匀”的,则在讨论ASL 时,可以不考虑它的因素。

因此,哈希表的ASL 是处理冲突方法和装载因子的函数。

可以证明:查找成功时有下列结果:线性探测再散列随机探测再散列从以上结果可见哈希表的平均查找长度是α的函数,而不是n 的函数。

这说明,用哈希表)111(21α-+≈nl S )1ln(1αα--≈nr S构造查找表时,可以选择一个适当的装填因子 ,使得平均查找长度限定在某个范围内。

数据结构实验报告(哈希表)

数据结构实验报告(哈希表)

散列表的设计实验报告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;}。

实验4—哈希表

实验4—哈希表

实验报告一、实验目的(1)掌握静态查找表和动态查找表的抽象数据类型特征。

(2)掌握将台查找表和动态查找表的实现方法。

(3)学会在顺序表、二叉排序树上设计查找算法,学会根据关键字特征设计哈希函数,设计哈希表,并实现哈希表查找过程。

二、实验内容与实验步骤[问题描述]真对你所在的集体(比如你所在的班级)中的人名设计一个哈希表,使得平均查找长度不超过R,完成相应的建表和查表的程序。

[基本要求]假设人名为中国人姓名的汉语拼音形式,待填入的哈希表的人名共有30个,取平均查找长度的上限为2。

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

[测试数据]取你周围熟悉的30个人的姓名。

[实现提示]如果随机函数自行构造,则应首先调整好随机函数,使其分布均匀。

人名的长度均不超过19个字符,最长的人名如:庄双双(Zhuang Shuangshuang)。

字符的取码方法可直接利用C语言中的toascii函数,并可对过长的人名先作折叠处理。

1 .存储结构定义typedef struct{ char *name; //名字所对应的拼音字母int k; //汉字拼音所对应的整数值}NAME;typedef struct //定义哈希表结构体{ char *name; //名字的拼音int k; //拼音所对应的整数int len; //查找的长度}HASH;2.姓名初始化名字以拼音的形式够成字符串,将字符串的各个字符所对应的ASCII码相加,所得的整数做为哈希表的关键字。

void InitkName() //姓名初始化函数{//人名初始化如下kName[0].name="cunjian";kName[1].name="mayun";kName[2].name="wangshi";kName[3].name="sunfeng";kName[4].name="wangzhe";kName[5].name="dongxi";kName[6].name="shenme";kName[7].name="lijie";kName[8].name="xiaoqun";kName[9].name="liuyangdong";kName[10].name="wuhan";kName[11].name="zhuzhishan";kName[12].name="chendongming";kName[13].name="mayi";kName[14].name="huangxia";kName[15].name="wangyan";kName[16].name="zhoutao";kName[17].name="jiangzhenyu";kName[18].name="wangdan";kName[19].name="wangming";kName[20].name="chenjunbo";kName[21].name="lilei";kName[22].name="wangjia";kName[23].name="zhangjianguo";kName[24].name="zhuqingqing";kName[25].name="huangmin";kName[26].name="haoyuhan";kName[27].name="liutao";kName[28].name="zhujiang";kName[29].name="lijun";char *f;int r,s0,i;for(i=0;i<NUM;i++){ s0=0;f=kName[i].name;for(r=0;*(f+r)!='\0';r++){s0=*(f+r)+s0;}kName[i].k=s0;//将字符串的各个字符所对应的ASCII码相加,所得的整数做为哈希表的关键字}}//初始化完成3.建立哈希表void CreateHashList() //建立哈希表函数{ int i;for(i=0; i<HASH_LENGTH;i++){ HashList[i].name=NULL;HashList[i].k=0;HashList[i].len=0;}for(i=0;i<HASH_LENGTH;i++){ int sum=0;int adr=(kName[i].k)%M;//哈希函数int d=adr;if(HashList[adr].len==0) //不冲突{HashList[adr].k=kName[i].k;HashList[adr].name=kName[i].name;HashList[adr].len=1;}else //发生冲突{do{ d=(d+kName[i].k%10+1)%M;//使用伪随机探测再散列法处理冲突 sum=sum+1; //查找次数加1}while (HashList[d].k!=0);HashList[d].k=kName[i].k;HashList[d].name=kName[i].name;HashList[d].len=sum+1;}}}4.查找哈希表void findList() //查找函数{ char name[20]={0};int s0=0,r,sum=1,adr,d;printf("请输入姓名的拼音:");scanf("%s",name);for(r=0;r<20;r++) //求出姓名的拼音所对应的整数,即关键字s0=name[r]+s0;adr=s0%M;d=adr;if(HashList[adr].k==s0)//分3种情况进行判断printf("\n查找完毕\n姓名:%s 关键字:%d ",HashList[d].name,s0);else if (HashList[adr].k==0)printf("没有这个姓名!");else{ int g=0;do{ d=(d+s0%10+1)%M;//伪随机探测再散列法处理冲突sum=sum+1;if(HashList[d].k==0){ printf("没有这个姓名!");g=1;}if(HashList[d].k==s0){ printf("\n姓名:%s 关键字:%d 查找长度为:%d",HashList[d].name,s0,sum);g=1;}}while(g==0);}}5.显示哈希表void Display() // 显示哈希表{ int i;float average=0;printf("\n地址\t姓名\t\t\t\t搜索长度\t关键字\n"); //显示的格式for(i=0; i<50; i++){ printf("%d ",i);printf("\t %s ",HashList[i].name);printf("\t\t\t%d ",HashList[i].len);printf("\t\t%d ",HashList[i].k);printf("\n");}}6.主函数程序设计void main(){ char x;InitkName();CreateHashList();printf("\n--------这是一个哈希表查找系统-------\n");printf("请选择相应的操作:\n");while(1){ printf("1. 显示哈希表2. 查找3. 退出\n");cin>>&x;switch(x){case '1':Display(); cout<<endl;break;case '2':findList();cout<<endl;break;case '3':exit(0);}}}三、实验环境操作系统:windows7调试软件名称vc++6.0四、实验过程与分析你的查找过程的平均查找长度是多少?最坏情况下的查找长度是多少?答:平均长度为1.8 不超过规定的2。

哈希查找数据结构实验报告

哈希查找数据结构实验报告

引言概述:哈希查找是一种高效的数据结构,它通过将关键字映射为哈希码,将数据存储在哈希表中,从而实现快速的查找操作。

本实验报告将详细介绍哈希查找的原理、实现方法、效率分析以及实验结果,并探讨其在实际应用中的优缺点。

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

数据结构实验报告四一一哈希表查找名字(字符串)实验题目:哈希表查找名字(字符串)实验目标:输入一组名字(至少50个),将其保存并利用哈希表查找。

输出哈希查找冲突次数,哈希表负载因子、查找命中率。

数据结构:哈希表和数组(二维)。

二维数组用于静态顺序存储名字(字符串),哈希表采用开放定址法,用于存储名字(字符串)对应的关键字并实现对名字(字符串)的查找。

需要的操作有:1.关键字求取(主函数中两次出现,未单独编为函数)关键字key=abs (字符串首位ASCII码值-第二位ASCII码值+第([n]+i )位ASCII码值撮后一位ASCII码值-倒数第二位ASCII码值)*字符串长度(abs为求整数绝对值的函数)。

2.处理关键字的哈希函数(Hash)利用平方取中法求关键值key在哈希表中的位置。

公式add=(key*key)%1000/LENGTH(add为key在哈希表中的地址)。

int Hash(i nt 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);coun t++;}}4.哈希表初始化(InitHash)void InitHash(int Hashtable[]){int i;for(i=0;i<LENGTH;i++)Hashtable[i]=-1;}5.向哈希表中插入关键字(InsertHash)void In sertHash(i nt key,i nt Hashtable[]){int add;add=Hash(key);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)(函数库vmath.h> 包含)算法设计:1建立长度为LENGTH的哈希表Hash ( LENGTH M体值由宏定义决定)。

2输入要插入的字符串总数num ( num小于等于LENGTH,再输入num个字符串,将这num个字符串的关键值key 计算出来后插入哈希表中。

3 输出哈希表(帮助调试用,并非实验目的) 。

4 依次查找这num 个字符串对应的关键字在哈希表中位置,并统计冲突次数,记为count。

根据公式计算负载因子和命中率(负载因子=表中填入的记录数/哈希表的长度,命中率=元素个数/查找次数)。

输出元素个数、冲突次数、查找次数、负载因子、命中率。

源程序(将LENGTH定义为60,实际调试中定义为60和100各一次):#include<stdio.h>#include<stdlib.h>#include<math.h>#include<string.h>#define LENGTH 60 /*实际调试中定义为60和100各一次*/int Hash(int key);int Collision(int key,int Hashtable[]);void InitHash(int Hashtable[]);void InsertHash(int key,int Hashtable[]);int SearchHash(int key,int Hashtable[]);void PrintHash(int Hashtable[]);int count=0,num=0;void main(){int i,key,collapsetime,searchtime,Hash[LENGTH];float loadelem,hitprob;char names[LENGTH][20];InitHash(Hash);printf("input the number of names(number<=%d).\n",LENGTH); scanf("%d",&num);printf("input names.\n"); for(i=0;i<num;i++){ scanf("%s",&names[i]);key=(abs((int)names[i][0]-(int)names[i][1]+(int)names[i][strlen(names[i])/2]-(int)names[i][str len(names[i])-2]-(int)names[i][strlen(names[i])-1]))*strlen(names[i]);/*上式为关键字求取,公式:关键字key=abs (字符串首位ASCII码值-第二位ASCII 码值+第([n/2]+1 )位ASCII码值-最后一位ASCII码值-倒数第二位ASCII码值)*字符串长度( abs 为求整数绝对值的函数) 。

*/InsertHash(key,Hash);}count=0;/* 将count 置零,清除插入过程中产生的冲突次数*/PrintHash(Hash);for(i=0;i<num;i++) {key=(abs((int)names[i][0]-(int)names[i][1]+(int)names[i][strlen(names[i])/2]-(int)names[i][str len(names[i])-2]-(int)names[i][strlen(names[i])-1]))*strlen(names[i]);/* 上式为关键字求取,公式同上*/SearchHash(key,Hash);}collapsetime=count; searchtime=count+num;loadelem=(float)num/LENGTH; hitprob=(float)num/searchtime;printf(" 元素个数:%d\n",num);printf(" 冲突次数:%d\n",collapsetime);printf(" 查找次数:%d\n",searchtime);printf(" 负载因子:%f\n",loadelem); printf(" 命中率=总人数/ 查找数:%f\n",hitprob);}int Hash(int key)/* 处理关键字的哈希函数*/{ return((key*key)/1000%LENGTH);}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++;/* 统计冲突次数*/}}void InitHash(int Hashtable[])/* 初始化哈希表*/{int i; for(i=0;i<LENGTH;i++)Hashtable[i]=-1;}void InsertHash(int key,int Hashtable[])/* 向哈希表中插入关键字*/{int add; add=Hash(key);if(Hashtable[add]==-1)Hashtable[add]=key;else { add=Collision(key,Hashtable);/* 处理哈希表中冲突,注意:这里count 也会计数,所以结束插入过程后应将count 清零*/Hashtable[add]=key;}}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;}void PrintHash(int Hashtable[])/* 输出哈希表(帮助调试用) */{int i;for(i=0;i<LENGTH;i++)if(Hashtable[i]!=-1)prin tf("%3d:%d\n",i+1,Hashtable[i]);}截图第一组(LENGTH宏定义为60) 输入:50个名字(字符串,采用英文单词) 输出结果:输出:1.哈希表(帮助调试用)2.实验要求的各项参数 元素个数:50,冲突次数:77,查找次数:127,负载因子:0.833333,命中率:1 1根据线性探测在散列成功查找时的公式ASL=(1+ )(其中,ASL 表示平均查找长度,a 表 示负载因子)。

ASL=3.5总平均查找次数为175,平均命中率为0.285714。

显然,本程序实现的哈希查找在本次试验中优于平均状况。

相关文档
最新文档