数据结构课程设计-散列表的设计与实现

合集下载

散列表数据结构课程设计

散列表数据结构课程设计

散列表数据结构课程设计一、课程目标知识目标:1. 理解散列表(哈希表)的基本概念,掌握其数据结构特点及实现原理;2. 学会使用散列表解决实际问题,如查找、插入和删除等操作;3. 掌握解决散列表冲突的方法,如线性探测、二次探测和链地址法等;4. 了解散列表在不同编程语言中的应用和实现。

技能目标:1. 能够运用散列表实现高效的数据存储和检索,提高编程解决问题的能力;2. 学会分析散列表的性能特点,如时间复杂度和空间复杂度,并进行优化;3. 能够运用散列表解决实际问题,培养编程思维和解决问题的能力;4. 掌握调试和优化散列表程序的方法,提高程序质量和效率。

情感态度价值观目标:1. 培养学生对数据结构与算法的兴趣,激发学习热情,形成主动探究的学习习惯;2. 培养学生的团队合作意识,学会在团队中分工协作,共同解决问题;3. 增强学生的创新意识,鼓励尝试不同的解决方案,提高解决问题的灵活性;4. 培养学生严谨、踏实的科学态度,注重算法的实际应用和优化。

本课程针对高年级学生,结合学科特点和教学要求,注重理论与实践相结合,通过散列表数据结构的学习,提高学生的编程能力和解决问题的能力,培养学生良好的学习态度和团队合作精神。

课程目标具体、可衡量,便于后续教学设计和评估。

二、教学内容1. 散列表基本概念:介绍散列表的定义、作用及其在数据结构中的地位;- 教材章节:第XX章XX节;- 内容:散列表的定义、散列函数、散列值、冲突和解决方法。

2. 散列表的实现原理:- 教材章节:第XX章XX节;- 内容:线性探测法、二次探测法、链地址法等散列表实现方式及其优缺点。

3. 散列表的操作:- 教材章节:第XX章XX节;- 内容:散列表的查找、插入和删除操作及其时间复杂度分析。

4. 散列表性能分析:- 教材章节:第XX章XX节;- 内容:时间复杂度、空间复杂度、装填因子及其对性能的影响。

5. 散列表应用实例:- 教材章节:第XX章XX节;- 内容:实际应用场景、编程实现、性能评估与优化。

数据结构课程设计-散列表的设计与实现

数据结构课程设计-散列表的设计与实现

榆林学院14届课程设计《散列表的设计与实现》课程设计说明书学生姓名:学号:院系:信息工程学院专业:计算机科学与技术班级:计14本1指导教师:答辩时间:2015年 12 月 31 日摘要 (1)Abstract (2)第一章绪论 (3)1. 数据结构简介 (3)2. 应用技术领域及范围 (3)3.设计的原理、方法和主要内容 (3)第二章需求分析 (4)1. 任务需求 (4)2. 功能需求 (4)3. 设计目的 (4)4. 设计要求 (4)第三章系统设计 (6)1. 设计思想 (6)2. 实现方法 (6)3. 主要模块 (6)4. 系统功能设计 (6)第四章系统实现及调试 (8)1. 系统功能流程 (8)2. 功能模块实现及调试 (9)总结 (11)参考文献 (11)散列表的设计与实现所涉及到的操作算法都是以链表或顺序表的基本运算作为基础的,此程序通过通讯录实现,包括建立通讯录,添加记录,查询记录,删除记录,显示记录,修改记录。

通过顺序表存储结构实现数据的输入,实现各子程序过程的演示,对异常输入信息报错。

关键字:新建通讯录,添加记录,查询记录,修改记录,删除记录,显示记录,散列表,散列函数,处理冲突AbstractThe design and implementation of the hash table are based on the basic operations of the list or sequence table. This program is implemented by the address book, including the establishment of the address book, adding records, record, delete records, record, modify records. Through sequential table storage structure to achieve data input, to achieve the process of the subroutine, the exception of the input information.Key words: new address book, add records, record, modify records, delete records, display records, hash table, hash function, handling conflict.第一章绪论1. 数据结构简介数据结构是计算机程序设计的重要理论设计基础,它不仅是计算机学科的核心课程,而且成为其他理工专业的热门选修课。

课程设计散列表

课程设计散列表

课程设计散列表一、教学目标本章节的教学目标分为三个维度:知识目标、技能目标和情感态度价值观目标。

1.知识目标:通过本章节的学习,学生需要理解散列表的基本概念,包括散列表的定义、特点和应用场景;掌握散列表的实现方法,包括数组、链表等;了解散列表的常见操作,如插入、删除和查找。

2.技能目标:学生需要能够运用散列表解决实际问题,如实现一个简单的散列表数据结构,并进行基本的插入、删除和查找操作;能够分析散列表的时间和空间复杂度,并评价其性能。

3.情感态度价值观目标:培养学生对计算机科学和数据结构的热情和兴趣,提高学生的问题解决能力和创新思维能力。

二、教学内容本章节的教学内容主要包括散列表的基本概念、实现方法和常见操作。

1.散列表的基本概念:介绍散列表的定义、特点和应用场景,使学生了解散列表的概念和背景知识。

2.散列表的实现方法:讲解散列表的实现方法,包括数组、链表等,让学生掌握散列表的基本实现技巧。

3.散列表的常见操作:介绍散列表的插入、删除和查找等常见操作,并通过实例演示和练习让学生熟练掌握。

三、教学方法为了激发学生的学习兴趣和主动性,本章节将采用多种教学方法相结合的方式进行教学。

1.讲授法:通过讲解散列表的基本概念、实现方法和常见操作,让学生掌握散列表的基本知识。

2.案例分析法:通过分析实际应用场景和实例,使学生了解散列表的应用价值和实际操作技巧。

3.实验法:安排实验课,让学生亲自动手实现散列表并进行插入、删除和查找操作,培养学生的实践能力。

四、教学资源为了支持教学内容和教学方法的实施,丰富学生的学习体验,将选择和准备以下教学资源:1.教材:选择一本与散列表相关的教材,作为学生学习的主要参考资料。

2.参考书:提供一些与散列表相关的参考书籍,供学生深入学习和拓展知识。

3.多媒体资料:制作散列表的教学PPT和视频教程,以图文并茂的形式讲解散列表的知识点。

4.实验设备:准备计算机和网络设备,以便进行实验课的教学和实践操作。

数据结构课程设计-散列法的研究大全

数据结构课程设计-散列法的研究大全

数据结构课程设计-散列法的研究大全第一篇:数据结构课程设计-散列法的研究大全学院:班级:完成人:姓指导教师:数据结构课程设计说明书信息科学与工程学院计算机科学与技术名:学号:山东科技大学 2013年12月25日课程设计任务书一、课程设计题目:散列法的实验研究二、课程设计应解决的主要问题:(1)数据元素的输入和输出(2)线性再散列法建立哈希表(3)二次探测再散列法建立哈希表(4)链地址法建立哈希表(5)线性再散列法进行数据查找(6)二次探测再散列法进行数据查找(7)链地址法进行数据查找(8)退出系统三、任务发出日期: 2013-10-01 课程设计完成日期: 2013-12-20小组分工说明小组编号 7 题目:散列法的实验研究小组分工情况:一人独立完成所有工作。

组长签字: 2013 年 12 月 31 日指导教师对课程设计的评价成绩:指导教师签字:年月日目录1.需求分析说明2.概要设计说明3.详细设计说明4.调试分析5.用户使用说明6.课程设计总结7.测试结果8.参考书目-3-4-5-7-8-10-10-12需求分析说明内部排序教学软件的总体功能要求:散列法中,散列函数构造方法多种多样,同时对于同一散列函数解决冲突的方法也可以不同。

两者是影响查询算法性能的关键因素。

对于几种典型的散列函数构造方法,做实验观察,不同的解决冲突方法对查询性能的影响。

基本功能如下:(1)界面友好,易与操作。

采用菜单方式进行选择。

(2)实现三种方法进行哈希表的构造。

包括线性再散列法、二次探测再散列法和链地址法。

(3)根据三种构造方法分别进行数据元素的查找,若查找成功,则同时输出探查/冲突次数。

以下是各功能模块的功能描述: 1.主函数模块本模块的主要功能是初始化图形界面,调用各模块,实现功能。

2.构造哈希表子模块本模块的主要功能是采用线性再散列法、二次探测再散列法、链地址法三种方法构造哈希表。

3.查找功能及输出子模块本模块的主要功能是在采用线性再散列法、二次探测再散列法、链地址法三种方法构造哈希表后,采用相应的方法对键入的数据进行查找,并计算探查/冲突次数。

数据结构报告——散列表、哈希表

数据结构报告——散列表、哈希表

数据结构实验报告班级:姓名:学号:时间:一、题目散列表的设计二、要求1、问题描述针对某个集体中人名设计一个散列表,使得平均查找长度不超过R,并完成相应的建表和查表程序。

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

散列函数用除留余数法构造,用伪随机探测再散列法处理冲突3、测试数据取读者周围较熟悉的30人的姓名。

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

人名的长度不超过20个字符。

可先对过长的人名作折叠处理。

三、设计思想1、散列函数的构造方法:散列列函数的构造方法有四种:平方取中法、除余法、相乘取整法、随机数法。

这里用了除余法,该方法是最为简单常用的一种方法。

它是以表长m来除关键字,取其余数作为散列地址,即 h(key)=key%m该方法的关键是选取m。

选取的m应使得散列函数值尽可能与关键字的各位相关。

m最好为素数。

【例】若选m是关键字的基数的幂次,则就等于是选择关键字的最后若干位数字作为地址,而与高位无关。

于是高位不同而低位相同的关键字均互为同义词。

【例】若关键字是十进制整数,其基为10,则当m=100时,159,259,359,…,等均互为同义词。

2、冲突的处理:(1)冲突两个不同的关键字,由于散列函数值相同,因而被映射到同一表位置上。

该现象称为冲突(Collision)或碰撞。

发生冲突的两个关键字称为该散列函数的同义词(Synonym)。

(2)安全避免冲突的条件最理想的解决冲突的方法是安全避免冲突。

要做到这一点必须满足两个条件:①其一是|U|≤m②其二是选择合适的散列函数。

这只适用于|U|较小,且关键字均事先已知的情况,此时经过精心设计散列函数h有可能完全避免冲突。

(3)冲突不可能完全避免通常情况下,h是一个压缩映像。

虽然|K|≤m,但|U|> m,故无论怎样设计h,也不可能完全避免冲突。

因此,只能在设计h时尽可能使冲突最少。

数据结构课程设计(散列表计算程序相近度)

数据结构课程设计(散列表计算程序相近度)

数据结构课程设计报告对于两个C程序,设计并实现两种不同的基于散列表的检测算法,计算两个程序的相近度,并分析比较两种算法的效率。

——散列表班级:软件112班**:***指导教师:兰红成绩:信息工程学院2013年1月6日目录1 需求分析 (3)1.1 主要任务 (3)1.2 课题要求 (3)1.3 主要功能 (3)1.4 主要工作 (3)1.5 重点解决问题 (3)2 概要设计 (4)2.1 抽象数据 (4)2.2 头文件及宏、结构体定义 (6)2.3 主程序流程 (7)2.4 各程序模块层次关系 (7)3 详细设计 (8)3.1 模块实现 (8)3.1.1 主要模块(函数) (8)3.2 主程序流程图 (12)4 调试分析 (13)4.1 遇到的问题 (13)4.1.1 关于程序运行时间的计算 (13)4.2 程序代码改进 (14)4.2.1 打开文件接收字符部分 (14)4.3 算法时空分析 (16)4.3.1 SortKey()复杂度 (16)4.3.2 OFind()函数复杂度 (17)4.3.3 CheckKeyword()函数复杂度 (17)4.4 程序设计回顾 (17)4.5 经验和体会 (18)5 测试结果 (20)5.1 简单程序测试 (20)5.1.1 测试文件内容 (20)5.1.2 程序输入界面 (20)5.1.3 测试运行结果 (21)5.2 复杂程序测试 (22)5.2.1 测试文件内容 (22)5.2.2 程序输入界面 (23)5.2.3 测试运行结果 (23)参考文献 (25)附录:源代码 (25)1 需求分析1.1 主要任务对于两个C程序,设计并实现两种不同的基于散列表的检测算法,计算两个程序的相近度,并分析比较两种算法的效率。

1.2 课题要求1. 分别读取两个C程序文件(InFile1.cpp, InFile2.cpp),识别其中的关键字并统计频度,分别生成两个文件,保存关键字名称和对应频度(OutFile1.txt, OutFile2.txt);2. 自行设计散列函数,分别利用开放地址法和链地址法构建C语言关键字的散列表。

数据结构课程设计之散列表的设计与实现

数据结构课程设计之散列表的设计与实现

##大学数据结构课程设计报告题目:散列表的设计与实现院(系):计算机工程学院学生姓名:班级:学号:起迄日期: 2011.6.19-6.30指导教师:2010—2011年度第 2 学期一、需求分析1.问题描述:该题目要求设计散列表实现电话号码的查找,在建立散列表时分别要用姓名和电话号码作为关键字来建立,在建立时设计不同的散列函数以及利用不同的解决冲突的方法记录冲突的次数。

2.基本功能:本程序为实现对电话号码及其主要信息进行保存并查找,通过利用散列表实现查找功能。

实现了折叠法和除留余数法构造哈希函数,而在处理冲突时又分别用到了线性探测再散列和二次探测再散列。

3.输入输出:本程序需要输入的用户信息包含三个数据:姓名、电话号码、地址。

所用的数据类型是指针,而三个信息均为字符串(字符数组),并注意在输入姓名时需要输入拼音以便可以用折叠法构造哈希函数。

输出的用户信息是字符串。

二、概要设计1.设计思路:本程序用到了字符串,所以首先要定义各个字符串的长度;其次创建一个折叠函数,利用大写字母的八进制表示;分别用姓名和电话号码建立哈希表,由于电话号码是字符串,所以用atoi函数将字符串转换成整型。

2.数据结构设计:ADT HashTableSearch{数据对象D:D是具有相同特性的数据元素的集合。

数据关系R:数据元素同属一个集合。

基本操作P:CreatHash(HashTable h,Data a);初始条件:哈希函数存在操作结果:以a为关键字建立哈希表EQ(x,y);初始条件:哈希表已建立操作结果:验证两个关键字SearchHash(h,c);初始条件:哈希表已经建立操作结果:查找信息并输出冲突数}ADT HashTableSearch3.软件结构设计:Get函数void getmessage();打印函数void display();折叠函数int floding(char*);哈希函数int Hash(char*);冲突函数Status collision(int ,int);创建哈希表void CreatHash(HashTable*,Data*); 查找函数void SearchHash(HashTable*,int );三、详细设计#include<stdio.h>#include<string.h>#include<stdlib.h>#define SUCCESS 1#define UNSUCCESS 0#define DUPLICATE -1#define MAXSIZE 20 //数量#define MAX_SIZE 20//信息长度#define hashsize 51//hashtable长度最好为质数typedef int Status;typedef struct Data{char name[20];char tel[20];char add[20];};typedef struct{Data *elem[hashsize];int count;int sizeindex;}HashTable;int num;Data *a=0;HashTable h;Get函数void getmessage(){printf("需要输入用户的数量:");scanf("%d",&num);a=(Data*)malloc(num*sizeof(Data));for(int i=0;i<num;i++){printf("输入第%d用户的名字:",i+1);scanf("%s",a[i].name);printf("输入第%d用户的电话号码:",i+1);scanf("%s",a[i].tel);printf("输入第%d用户的地址:",i+1);scanf("%s",a[i].add);}}打印函数void display(){int i;for(i=0;i<num;i++)printf("名字%s 电话号码%s 地址%s\n",a[i].name,a[i].tel,a[i].add); }折叠函数int floding(char *s)// 用户名的折叠法{char str[20];char *a;int sum=0;strcpy(str,s);strupr(str);a=str;while(*a!=0){sum+=*a;*a++;}return sum;}哈希函数int Hash1(char *str)//折叠法哈希函数{int n;int m;n=floding(str);m=n%hashsize;return m;}int Hash2(char *str)//除留余数法哈希函数{int n;n=atoi(str);m=n%hashsize;return m;}解决冲突函数Status collision1(int &p,int &c)//线性探测再散列法解决冲突{int i,q;i=c/2+1;while(i<hashsize){if(c%2==0){c++;q=(p+i)%hashsize;if(q>=0)return q;elsei=c/2+1;}else{q=(p-i)%hashsize;c++;if(q>=0)return q;elsei=c/2+1;}}return UNSUCCESS;}Status collision2(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 CreatHash1(HashTable *h,Data *a)//以姓名为关键字建立哈希表{int i,p,q,c;int n;printf("1.线性探测再散列\n");printf("2.二次探测再散列\n");printf("请选择解决冲突的方式:");scanf("%d",&n);for(i=0;i<num;i++){c=0;p=Hash1(a[i].name);q=p;while(h->elem[q]!=0){switch(n){case 1:q=collision1(p,c);break;case 2:q=collision2(p,c);break;}}h->elem[q]=&a[i];h->count++;printf("第%d个用户冲突的次数为%d次\n",i+1,c);}printf("以姓名方式建表成功\n");}void CreatHash2(HashTable *h,Data *a)//以电话号码为关键字建立哈希表{int i,p,q,c;int n;printf("1.线性探测再散列\n");printf("2.二次探测再散列\n");printf("请选择解决冲突的方式:");scanf("%d",&n);for(i=0;i<num;i++){c=0;p=Hash1(a[i].name);q=p;while(h->elem[q]!=0){switch(n){case 1:q=collision1(p,c);break;case 2:q=collision2(p,c);break;}}h->elem[q]=&a[i];h->count++;printf("第%d个用户冲突的次数为%d次\n",i+1,c);}printf("以电话号码方式建表成功\n");}Status EQ(char *x,char *y)//验证两个关键字是否一致{if(strcmp(x,y)==0)return 1;else return 0;}查找函数void SearchHash1(HashTable *h,int &c){ char str[20];int p,q;printf("请输入要查找的姓名:");scanf("%s",str);p=Hash1(str);q=p;while(h->elem[q]->name!=0&&!EQ(str,h->elem[q]->name))q=collision1(p,c);if(EQ(str,h->elem[q]->name)){printf("查找成功,用户信息为:\n");printf("姓名:%s 电话号码:%s 地址:%s \n",h->elem[q]->name,h->elem[q]->tel,h->elem[q]->add);}else printf("查找的用户不存在");}void SearchHash2(HashTable *h,int &c){ char str[20];int p,q;printf("请输入要查找的电话号码:");scanf("%s",str);p=Hash2(str);q=p;while(h->elem[q]->tel!=0&&!EQ(str,h->elem[q]->tel))q=collision2(p,c);if(EQ(str,h->elem[q]->tel)){printf("查找成功,用户信息为:\n");printf("姓名:%s 电话号码:%s 地址:%s \n",h->elem[q]->name,h->elem[q]->tel,h->elem[q]->add);}else printf("查找的用户不存在");}int main(){int m,c;while(1){printf(" ------------------------\n");printf(" 欢迎使用电话号码查找系统\n");printf(" ------------------------\n");printf(" 1.添加用户信息\n");printf(" 2.显示所有已添加用户的信息\n");printf(" 3.以姓名建立散列表\n");printf(" 4.以电话号码建立散列表\n");printf(" 5.输入姓名查找用户信息\n");printf(" 6.输入电话号码查找用户信息\n");printf(" 7.退出系统\n");printf(" **********************************************\n");printf(" *特别声明:输入名字时请输入拼音,不要输入汉字*\n");printf(" **********************************************\n");printf("请输入命令:");scanf("%d",&m);switch(m){case 1:getmessage();break;case 2:display();break;case 3:CreatHash1(&h,a);break;case 4:CreatHash2(&h,a);break;case 5:SearchHash1(&h,c);break;case 6:SearchHash2(&h,c);break;case 7: printf("谢谢您的使用\n");return 0;break;default :printf("输入数字不合法,请重新输入\n");break;}}return 0;}调用函数图如下:四、调试分析编写程序时,先是没有考虑到程序运行时需要字符串和整型数据之间的转换,修改中用到了atoi函数。

数据结构实验 散列表实验报告

数据结构实验 散列表实验报告

数据结构实验散列表实验报告一、实验目的本次实验的主要目的是深入理解和掌握散列表这种数据结构的基本原理、实现方法以及其在实际应用中的性能特点。

通过实际编写代码和进行相关测试,提高对散列表的操作能力,并能够分析和解决在使用散列表过程中可能遇到的问题。

二、实验原理散列表(Hash Table)是一种根据关键码值(Key value)而直接进行访问的数据结构。

通过一个特定的函数(哈希函数)将关键码映射到表中的一个位置来访问记录,以加快查找的速度。

这个映射函数称为哈希函数,存放记录的数组称为哈希表。

哈希函数的设计至关重要,它需要尽可能地将不同的关键码值均匀地分布在哈希表中,以减少冲突的发生。

常见的哈希函数有直接定址法、除留余数法、数字分析法等。

冲突解决方法也是散列表中的重要部分。

当不同的关键码通过哈希函数映射到相同的位置时,就会产生冲突。

常见的冲突解决方法有开放定址法(线性探测、二次探测等)和链地址法。

三、实验环境本次实验使用的编程语言为C++,开发工具为Visual Studio 2019。

四、实验内容1、哈希函数的实现采用除留余数法实现哈希函数。

代码如下:```cppint hashFunction(int key, int tableSize) {return key % tableSize;}```2、散列表的创建与初始化使用动态数组创建散列表,并将所有位置初始化为空。

```cppclass HashTable {private:int table;int size;public:HashTable(int tableSize) {size = tableSize;table = new intsize;for (int i = 0; i < size; i++){tablei =-1; //-1 表示为空}}~HashTable(){delete table;}};```3、数据插入操作采用线性探测法解决冲突。

散列表的设计与实现

散列表的设计与实现

散列表的设计与实现1程序最终实现结果及分析散列表实现的电话查找系统。

各功能模块的详细介绍。

1.1功能模块1实现结果1.1.1详细设计模块名称:密码登录验证功能说明:该模块主要是通过密码进入主菜单密码输入有三次机会,三次输入错误自动结束程序。

输入参数:密码为任一字符串。

输出:密码正确提示进入系统。

不正确提示错误。

1.1.2界面设计及测试结果1.2.1详细设计模块名称:一次性添加所有用户信息功能说明:该模块包括选择要添加的个数。

先输入个数之后再输入各用户信息。

输入参数:依次为:用户名,电话号码,地址。

各个参数都是字符串类型。

1.2.2界面设计及测试结果1.3.1详细设计模块名称:显示一次性添加的所有用户信息功能说明:该模块主要是读取用户一次性输入的所有用户信息。

输出:按用户名,电话号码,地址的顺序显示一行记录。

输出各条记录。

1.3.2界面设计及测试结果1.4功能模块4实现结果1.4.1详细设计模块名称:以用户名建立哈希表(链地址解决冲突)功能说明:该模块用于以姓名建立哈希表并且用链地址解决冲突。

输入参数:按用户名,电话号码,地址的依次顺序在记录数组中提到。

各个参数都为字符串类型。

输出:字符串消息提示。

所调用其他功能构件及被调用的其他功能构件:我们调用了hashUser类(以用户名建立散列表的哈希类)的put方法,逐条放入记录建立散列表。

1.4.2界面设计及测试结果1.5功能模块5实现结果1.5.1详细设计模块名称:以电话号码建立哈希表(链地址解决冲突) 。

功能说明:该模块用于以电话号码建立哈希表并且用链地址解决冲突。

输入参数:按电话号码,用户名,地址的依次顺序在记录数组中提到。

各个参数都为字符串类型。

输出:字符串消息提示。

所调用其他功能构件及被调用的其他功能构件:我们调用了hashTel类(以电话号码建立散列表的哈希类)的put方法,逐条放入记录建立散列表。

1.6功能模块6实现结果1.6.1详细设计模块名称:查找并显示给定用户名的记录功能说明:该模块以用户名查找信息在执行该步骤之前先执行(3).输入参数:用户名,类型为字符串。

数据结构课程设计-利用散列表做一个电话号码查找系统

数据结构课程设计-利用散列表做一个电话号码查找系统

数据结构课程设计-利⽤散列表做⼀个电话号码查找系统【基本要求】(1)设每个记录有下列数据项:电话号码、⽤户名、地址;(2)从键盘输⼊各记录,分别以电话号码和⽤户名为关键字建⽴散列表;(3)采⽤⼀定的⽅法解决冲突;(4)查找并显⽰给定电话号码的记录;(5)查找并显⽰给定⽤户名的记录。

【选做内容】(1)系统功能的完善;(2)设计不同的散列函数,⽐较冲突率; (3)在散列函数确定的前提下,尝试各种不同类型处理冲突的⽅法,考察平均查找长度的变化。

⽤的C++开发,基本实现了3种哈希函数+3种解决冲突的⽅法。

因为要求同时有姓名散列与按号码散列,所以⽤了flag标记每次的散列类型,针对不同的要求对散列函数做了个别优化。

哈希表类的结构如下1class HashTable{2public:3 HashTable(int size = MAXSIZE-1);4 ~HashTable(){ delete[]E; delete[]tag; delete[]E2; delete[]tag2; }5int hash1(string name, int flag);//哈希函数1 除数求余法6int hash2(string tel);//哈希函数2 折叠法7int hash3(string tel);//哈希函数3 数字分析法8int solve1(int hashVal, int flag);//线性探测法解决冲突9int solve2(int hashVal, int flag);//⼆次探测法解决冲突10 Node* solve3(int hashVal, int flag);//拉链法解决冲突11 User input();//往电话薄中添加⽤户12void creat(int flag); //创建散列表13void show(int flag); //列出电话薄所有元素14void search(int flag,string at); //搜索指定⽤户15void searchByNode(int flag, string at); //拉链法搜索指定⽤户16void insert(int flag, User newUser); //插⼊17void del(int flag, string by);//删除18void save(int flag);//将电话薄保存⾄本地⽂件19int length; //要创建的电话本长度20 Node** ht;21private:22 User* E; //⽤户数组按姓名散列23 User* E2; //⽤户数组2 按电话号码散列24int* tag; //标记散列表1每个桶的存储状态 0为空 1为实25int* tag2;//标记散列表2每个桶的存储状态26int flag; //1表⽰是按姓名 2表⽰按电话号码新建的哈希表27int maxSize; //哈希表最⼤长度28int f;//⽐例因⼦主要⽤于折叠法29 };View CodeUser类的结构class User{public:string name;string tel;string address;bool operator==(const User&target){if (this->name == &&this->address == target.address&&this->tel == target.tel)return true;elsereturn false;}};哈希函数1int HashTable::hash1(string name,int flag) //除留求余法{int hashValue; long a = 0;switch (flag){case1:for (int i = 0; i < name.length(); i++)a += int(name[i]);hashValue = a%maxSize;break;case2:int temp = atof(name.c_str());hashValue = temp%maxSize;break;}return hashValue;};哈希函数2int HashTable::hash2(string tel) //折叠法--移位法{int hashValue;int temp; //移位法求和temp = atof(tel.substr(0, 3).c_str()) + atof(tel.substr(3, 3).c_str())+ atof(tel.substr(6, 3).c_str()) + atof(tel.substr(9, 2).c_str());//取计算之后的数的最后三位if (temp >= 999){char p[10];sprintf(p, "%d", temp);string lastThree = p;lastThree = lastThree.substr(lastThree.length() - 3, 3);hashValue = atof(lastThree.c_str());return hashValue;}hashValue = temp;return hashValue;};哈希函数3int HashTable::hash3(string tel)//数字分析法做哈希函数{int hashValue;hashValue = atof(tel.substr(8, 3).c_str()); //因为电话号码⼀般后4位不同return hashValue;};解决冲突的⽅法1.线性探测法int HashTable::solve1(int hashVal,int flag) //线性探查法处理冲突{int output = hashVal;switch (flag){case1:for (int j = 1; j < MAXSIZE; j++){output = (hashVal + j) % MAXSIZE;if (tag[output] == 0){tag[output] = 1;return output;}}return -1;break;case2:for (int j = 1; j < MAXSIZE; j++){output = (hashVal + j) % MAXSIZE;if (tag2[output] == 0){tag2[output] = 1;return output;}}return -1;default:break;}};2.⼆次探查法int HashTable::solve2(int hashVal, int flag) //⼆次探查法解决冲突{int i = hashVal; //i为初始桶号int k = 0; //k为探查次数int odd = 0; //odd为控制加减的标志int save; //缓存上⼀次的桶号switch (flag){case1:while (tag[i]==1){if (odd == 0){k++; save = i;i = (i + 2 * k-1) % MAXSIZE;odd = 1;}else{i = (save - 2 * k+1) % MAXSIZE;odd = 0;if (i<0){i = i + MAXSIZE;}}}return i;break;case2:while (tag2[i] == 1){if (odd == 0){k++; save = i;i = (i + 2 * k - 1) % MAXSIZE;odd = 1;}else{k++;i = (save - 2 * k + 1) % MAXSIZE;odd = 0;if (i<0){i = i + MAXSIZE;}}}return i;break;default:break;}};3.拉链法Node* HashTable::solve3(int hashVal, int flag)//拉链法解决冲突{int i = hashVal; //第i条链Node*p = ht[i]; //该链上的头指针while (p!=NULL)p = p->next;//往后遍历直到找到⼀个空节点⽤于存放userreturn p;};所有代码如下1 #include <iostream>2 #include <string>3 #include <fstream>45using namespace std;67const int MAXSIZE = 12;//默认最⼤表长89101112//存储项13class User{14public:15string name;16string tel;17string address;18bool operator==(const User&target)19 {20if (this->name == &&this->address == target.address&&this->tel == target.tel) 21return true;22else23return false;24 }25 };2627//⽤于拉链法28struct Node{29 User user;30 Node* next;31 };32class HashTable{33public:34 HashTable(int size = MAXSIZE-1);35 ~HashTable(){ delete[]E; delete[]tag; delete[]E2; delete[]tag2; }36int hash1(string name, int flag);//哈希函数1 除数求余法37int hash2(string tel);//哈希函数2 折叠法38int hash3(string tel);//哈希函数3 数字分析法39int solve1(int hashVal, int flag);//线性探测法解决冲突40int solve2(int hashVal, int flag);//⼆次探测法解决冲突41 Node* solve3(int hashVal, int flag);//拉链法解决冲突42 User input();//往电话薄中添加⽤户43void creat(int flag); //创建散列表44void show(int flag); //列出电话薄所有元素45void search(int flag,string at); //搜索指定⽤户46void searchByNode(int flag, string at); //拉链法搜索指定⽤户47void insert(int flag, User newUser); //插⼊48void del(int flag, string by);//删除49void save(int flag);//将电话薄保存⾄本地⽂件50int length; //要创建的电话本长度51 Node** ht;52private:53 User* E; //⽤户数组按姓名散列54 User* E2; //⽤户数组2 按电话号码散列55int* tag; //标记散列表1每个桶的存储状态 0为空 1为实56int* tag2;//标记散列表2每个桶的存储状态57int flag; //1表⽰是按姓名 2表⽰按电话号码新建的哈希表58int maxSize; //哈希表最⼤长度59int f;//⽐例因⼦主要⽤于折叠法60 };6162 HashTable::HashTable(int size)63 {64 maxSize = size; //⽤作除数65 E = new User[MAXSIZE];66 E2 = new User[MAXSIZE];67 tag = new int[MAXSIZE];68 tag2 = new int[MAXSIZE];69for (int i = 0; i < MAXSIZE; i++)70 {71 tag[i] = 0;72 tag2[i] = 0;73 }74 f = maxSize / 512; //⽤于折叠法产⽣的哈希值过⼤保留3位数的地址范围为0~51175 ht = new Node*[maxSize]; //存放节点的⼀维数组拉链法76 };7778int HashTable::hash1(string name,int flag) //除数求余法79 {80int hashValue; long a = 0;81switch (flag)82 {83case1:84for (int i = 0; i < name.length(); i++)85 a += int(name[i]);86 hashValue = a%maxSize;87break;88case2:89int temp = atof(name.c_str());90 hashValue = temp%maxSize;91break;9293 }94return hashValue;95 };9697int HashTable::hash2(string tel) //折叠法--移位法98 {99int hashValue;100int temp; //移位法求和101 temp = atof(tel.substr(0, 3).c_str()) + atof(tel.substr(3, 3).c_str())102 + atof(tel.substr(6, 3).c_str()) + atof(tel.substr(9, 2).c_str());103//取计算之后的数的最后三位104if (temp >= 999)105 {106char p[10];107 sprintf(p, "%d", temp);108string lastThree = p;109 lastThree = lastThree.substr(lastThree.length() - 3, 3);110 hashValue = atof(lastThree.c_str());111return hashValue;112 }113 hashValue = temp;114return hashValue;115 };116117int HashTable::hash3(string tel)//数字分析法做哈希函数118 {119int hashValue;120 hashValue = atof(tel.substr(8, 3).c_str()); //因为电话号码⼀般后4位不同121return hashValue;122 };123124int HashTable::solve1(int hashVal,int flag) //线性探查法处理冲突125 {126int output = hashVal;127switch (flag)128 {129case1:130for (int j = 1; j < MAXSIZE; j++)131 {132 output = (hashVal + j) % MAXSIZE;133if (tag[output] == 0)134 {135 tag[output] = 1;136return output;137 }138 }139return -1;140break;141case2:142for (int j = 1; j < MAXSIZE; j++)143 {144 output = (hashVal + j) % MAXSIZE;145if (tag2[output] == 0)146 {147 tag2[output] = 1;148return output;149 }150 }151return -1;152default:153break;154 }155156 };157158int HashTable::solve2(int hashVal, int flag) //⼆次探查法解决冲突159 {160int i = hashVal; //i为初始桶号161int k = 0; //k为探查次数162int odd = 0; //odd为控制加减的标志163int save; //缓存上⼀次的桶号164switch (flag)165 {166case1:167while (tag[i]==1)168 {169if (odd == 0)170 {171 k++; save = i;172 i = (i + 2 * k-1) % MAXSIZE;173 odd = 1;174 }175else176 {177 i = (save - 2 * k+1) % MAXSIZE;178 odd = 0;179if (i<0)180 {181 i = i + MAXSIZE;182 }183 }184 }185return i;186break;187case2:188while (tag2[i] == 1)189 {190if (odd == 0)191 {192 k++; save = i;193 i = (i + 2 * k - 1) % MAXSIZE;194 odd = 1;195 }196else197 {198 k++;199 i = (save - 2 * k + 1) % MAXSIZE;200 odd = 0;201if (i<0)202 {203 i = i + MAXSIZE;204 }205 }206 }207return i;208break;209default:210break;211 }212213 };214215/*216Node* HashTable::solve3(int hashVal, int flag)//拉链法解决冲突217218{219 int i = hashVal; //第i条链220221 Node*p = ht[i]; //该链上的头指针222 while (p!=NULL)223 p = p->next;//往后遍历直到找到⼀个空节点⽤于存放user 224 return p;225};226227void HashTable::searchByNode(int flag, string at)//调⽤拉链法搜索228{229 int i = hash1(at,1);230 Node** ht = new Node*[maxSize]; //存放节点的⼀维数组231 Node*p = ht[i]; //该链上的头指针232 while (p!=NULL&&p->!=at)233 {234 p = p->next;235 }236};237*/238 User HashTable::input()239 {240 User user;241 cout << "请输⼊姓名:" << endl;242 cin >> ;243 cout << "请输⼊电话号码:" << endl;244 cin >> user.tel;245 cout << "请输⼊地址:" << endl;246 cin >> user.address;247return user;248 };249250void HashTable::creat(int flag)251 {252switch (flag)253 {254case1: //按姓名哈希创建哈希表255for (int i = 0; i < length; i++)256 {257 User newUser = input();258int val = hash1(,1);259if (tag[val] == 1)260 val = solve1(val,1);//线性探测法解决冲突261 E[val] = newUser;262 tag[val] = 1;263 }264break;265case2: //按电话号码哈希创建哈希表266for (int i = 0; i < length; i++)267 {268 User newUser = input();269int val = hash1(newUser.tel,2);270if(tag2[val] == 1)271 val = solve1(val,2);//线性探测法解决冲突272 E2[val] = newUser;273 tag2[val] = 1;274 }275break;276 }277 };278void HashTable::show(int flag)279 {280switch (flag)281 {282case1:283for (int i = 0; i < MAXSIZE; i++)284 {285if (tag[i] == 1)286 cout << E[i].name << "" << E[i].tel << "" << E[i].address << " 位于: " << i << endl; 287 }288break;289case2:290for (int i = 0; i < MAXSIZE; i++)291 {292if (tag2[i] == 1)293 cout << E2[i].name << "" << E2[i].tel << "" << E2[i].address << " 位于: " << i << endl; 294 }295break;296 }297298 };299300void HashTable::search(int flag,string at) //at表⽰索引内容301 {302int i = 0;303switch (flag)304 {305case1: //调⽤线性探测法查找姓名306 i = hash1(at,1);307if (tag[i] == 1 && E[i].name != at)308 i = solve1(i, 2);309if (i < 0 || tag2[i] == 0)310 {311 cout << "查⽆此⼈!" << endl;312return;313 }314if (tag[i] == 1 && E[i].name == at)315 cout << E2[i].name << "" << E2[i].tel << "" << E2[i].address << endl;316break;317case2: //调⽤⼆次探测法查找电话号码318 i = hash2(at);319if (tag2[i] == 1&&E2[i].tel!=at)320 i = solve2(i,2);321if (i < 0||tag2[i]==0)322 {323 cout << "查⽆此⼈!" << endl;324return;325 }326if (tag2[i] == 1 && E2[i].tel==at)327 cout << E2[i].name << "" << E2[i].tel << "" << E2[i].address << endl;328break;329 }330 };331332void HashTable::insert(int flag, User newUser){333int i = -1;334switch (flag)335 {336case1:337 i = hash1(,1);338if (tag[i] == 1||E[i]==newUser)339 i = solve1(i, 1);340if (i < 0)341 {342 cout << "表满!插⼊失败!" << endl;343return;344 }345if (tag[i] == 0)346 {347 E[i] = newUser;348 tag[i] = 1;349 length++;350 cout << "插⼊成功" << endl;351 }352case2:353 i = hash1(newUser.tel,2);354if (tag2[i] == 1 || E2[i] == newUser)355 i = solve1(i, 2);356if (i < 0)357 {358 cout << "表满!插⼊失败!" << endl;359return;360 }361if (tag2[i] == 0)362 {363 E2[i] = newUser;364 tag2[i] = 1;365 length++;366 cout << "插⼊成功" << endl;367 }368default:369break;370 }371 };372373void HashTable::del(int flag, string by) //by表⽰按照何种标签进⾏删除374 {375int i = -1;376int select;//选择是否删除377switch (flag)378 {379case1: //调⽤线性探测法查找姓名380 i = hash1(by,1);381if (tag[i] == 1 && E[i].name != by)382 i = solve1(i, 2);383if (i < 0 || tag2[i] == 0)384 {385 cout << "查⽆此⼈!" << endl;386return;387 }388if (tag[i] == 1 && E[i].name == by)389 {390 cout << E2[i].name << "" << E2[i].tel << "" << E2[i].address << endl; 391 cout << "是否删除 0.删了 1.算了" << endl;392 cin >> select;393if (select == 0)394 tag[i] = 0;//伪删除395 }396break;397case2: //调⽤⼆次探测法查找电话号码398 i = hash2(by);399if (tag2[i] == 1 && E2[i].tel != by)400 i = solve2(i, 2);401if (i < 0 || tag2[i] == 0)402 {403 cout << "查⽆此⼈!" << endl;404return;405 }406if (tag2[i] == 1 && E2[i].tel == by)407 {408 cout << E2[i].name << "" << E2[i].tel << "" << E2[i].address << endl; 409 cout << "是否删除 0.删了 1.算了" << endl;410 cin >> select;411if (select == 0)412 tag2[i] = 0;//伪删除413 }414break;415 }416 };417418void HashTable::save(int flag)419 {420 fstream out1("电话薄(姓名散列).txt", ios::out);421 fstream out2("电话薄(号码散列).txt", ios::out);422switch (flag)423 {424case1:425for (int i = 0; i < maxSize; i++)426 {427if (tag[i] == 1)428 out1 << E[i].name << "" << E[i].tel << "" << E[i].address << endl; 429 }430 cout << "已存⾄电话薄(姓名散列).txt" << endl;431return;432break;433case2:434for (int i = 0; i < maxSize; i++)435 {436if (tag2[i] == 1)437 out2 << E2[i].name << "" << E2[i].tel << "" << E2[i].address << endl; 438 }439 cout << "已存⾄电话薄(号码散列).txt" << endl;440return;441break;442default:443break;444 }445446 };hashtable.h1 #include <iostream>2 #include <string>3 #include <fstream>4 #include "hashtable.h"5using namespace std;67//菜单8void menu()9 {10 cout << " ****************************" << endl;11 cout << "|| 0.建表 ||" << endl;12 cout << "|| 1.查看 ||" << endl;13 cout << "|| 2.搜索 ||" << endl;14 cout << "|| 3.添加 ||" << endl;15 cout << "|| 4.删除 ||" << endl;16 cout << "|| 5.保存 ||" << endl;17 cout << "|| 6.退出 ||" << endl;18 cout << " ****************************" << endl;1920 }2122int main()23 {24 User user;25int size;//第⼀次创建的数据量⼤⼩26int select;//主菜单选项27int select_;//⼦菜单选项28 cout << "欢迎使⽤电话簿" << endl;29 HashTable ht;30while (1)31 {32 menu();33 cin >> select;34switch (select)35 {36case0:37 cout << "第⼀次使⽤,请输⼊要新建的电话本⼤⼩:" << endl;38 cin >> size;39 ht.length = size;40 cout << "1.姓名散列 2.电话号码散列" << endl;41 cin >> select_;42 ht.creat(select_);43break;44case1:45 cout << "1.姓名散列 2.电话号码散列" << endl;46 cin >> select_;47 ht.show(select_);48break;49case2:50 cout << "1.按姓名查找 2.按电话号码查找" << endl;51 cin >> select_;52if (select_==1)53 {54 cout << "输⼊姓名" << endl;55string name;56 cin >> name;57 ht.search(1, name);58 }59else if (select_ == 2)60 {61 cout << "输⼊号码" << endl;62string tel;63 cin >> tel;64 ht.search(2, tel);65 }66else67 cout << "不合法操作" << endl;68break;69case3:70 user = ht.input();71 cout << "1.插⼊到姓名散列表 2.插⼊到电话号码散列" << endl;72 cin >> select_;73 ht.insert(select_,user);74break;75case4:76 cout << "1.根据姓名删除 2.根据电话号码删除" << endl;77 cin >> select_;78if (select_ == 1)79 {80 cout << "输⼊姓名" << endl;81string name;82 cin >> name;83 ht.del(1, name);84 }85else if (select_ == 2)86 {87 cout << "输⼊号码" << endl;88string tel;89 cin >> tel;90 ht.del(2, tel);91 }92else93 cout << "不合法操作" << endl;94break;95case5:96 cout << "1.保存姓名散列表到本地 2.保存电话号码散列表到本地" << endl;97 cin >> select_;98 ht.save(select_);99case6:100return0;101 }102 }103 }main.cpp通过这次课程设计,总结如下1. C++技艺不精,语法不熟悉,⽐如模版类与运算符重载,指针更是不⼤熟练。

散列法的实验研究 课程设计报告

散列法的实验研究  课程设计报告

课程设计报告问题描述:(1) 散列法中,散列函数构造方法多种多样,同时对于同一散列函数解决冲突的方法也可以不同。

两者是影响查询算法性能的关键因素。

(2) 程序实现几种典型的散列函数构造方法,并观察,不同的解决冲突方法对查询性能的影响。

a.需求分析:散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构。

对不同的关键字可能得到同一散列地址,即key1≠key2,而f(key1)=f(key2),这种现象称冲突。

具有相同函数值的关键字对该散列函数来说称做同义词。

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

散列表的查找过程基本上和造表过程相同。

一些关键码可通过散列函数转换的地址直接找到,另一些关键码在散列函数得到的地址上产生了冲突,需要按处理冲突的方法进行查找。

对散列表查找效率的量度,依然用平均查找长度来衡量。

查找过程中,关键码的比较次数,取决于产生冲突的多少,产生的冲突少,查找效率就高,产生的冲突多,查找效率就低。

因此,影响产生冲突多少的因素,也就是影响查找效率的因素。

该课程设计要求比较几种哈希函数的构造方法和解决冲突的方法对查询性能的影响。

b.概要设计该程序实现对哈希函数的构造方法、处理冲突的方法及在哈希表中查找数据的功能。

用线性再散列方法建立哈希表,用代码实现为:typedef structint key;int si;}HashTable1;void CreateHashTable1(HashTable1 *H,int *a,int num)//哈希表线性探测在散列;{int i,d,cnt;for(i=0;i<HashSize;i++){H[i].key=0;H[i].si=0;}for(i=0;i<num;i++){cnt=1;d=a[i]%HashSize;if(H[d].key==0){H[d].key=a[i];H[d].si=cnt;}else{do{d=(d+1)%HashSize;cnt++;}while(H[d].key!=0);H[d].key=a[i];H[d].si=cnt;}printf("\n线性再探索哈希表已建成!");}用二次探测再散列建立哈希表,代码实现如下:void CreateHash3(HashTable3 *h,int *a,int num)//二次探索表{int i,p=-1,c,pp;for(i=0;i<num;i++){c=0;p=a[i]%HashSize;pp=p;while(h->elem[pp]!=NULL){pp=Collision(p,c);if(pp<0){printf("第%d个记录无法解决冲突\n",i+1);continue;}}h->elem[pp]=&(a[a[i]]);h->count++;printf("第%d个记录冲突次数为%d\n",i+1,c);}printf("\n建表完成!\n此哈希表容量为%d,当前表内存储的记录个数%d.\n",HashSize,h->count);}二次探测再散列法解决冲突int 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;elsei=c/2+1;}else{q=(p-i*i)%HashSize;c++;if(q>=0)return q;else i=c/2+1;}}return (-1);}用线性再散列法查找,代码实现如下:void SearchHash1(HashTable1 *h,int data) {int d;d=data%HashSize;if(h[d].key==data)printf("数字%d的探查次数为:%d\n",h[d].key,h[d].si);else{dod=(d+1)%HashSize;while(h[d].key!=data && d<HashSize);if(d<HashSize)printf("数字%d的探查次数为:%d\n",h[d].key,h[d].si);elseprintf("没有查找到你所输入的数\n");}用二次探测再散列法查找void SearchHash2(HashTable2 * h[],int data,int num){int d;Node *q;d=data%num;q=h[d]->link;while(q->key!=data && q->next!=NULL)q=q->next;if(q->next!=NULL)printf("数字%d的查找次数为:%d\n",q->key,q->next);elseprintf("没有找到你要查找的那个数\n");}用链地址法查找,代码实现如下:void CreateHashTable2(HashTable2 *ht[],int *a,int num)//哈希表链地址;{int i,d,cnt;Node *s,*q;for(i=0;i<num; i++){ht[i]=(HashTable2 *)malloc(sizeof(HashTable2)); ht[i]->link=NULL;}for(i=0;i<num;i++){cnt=1;s=(Node *)malloc(sizeof(Node));s->key=a[i];s->next=NULL;d=a[i]%num;if(ht[d]->link==NULL){ht[d]->link=s;s->si=cnt;}else{q=ht[d]->link;while(q->next!=NULL){q=q->next;cnt++;}cnt++;s->si=cnt;q->next=s;}}}c.详细设计(1)程序中结构体的定义typedef struct{int key;int si;}HashTable1;typedef struct node{int key;int si;struct node *next;}Node;typedef struct{Node *link;}HashTable2;typedef struct{int * elem[HashSize];int count;int size;}HashTable3;(2) 主函数模块void main(){int data;HashTable1 hash1[HashSize];HashTable2 * hash2[HashSize];HashTable3 * ha;ha=(HashTable3 *)malloc(sizeof(HashTable3));for(int i=0;i<HashSize;i++)ha->elem[i]=NULL;ha->count=0;ha->size=HashSize;int a[MaxSize];while(1){printf("\n ┏━━━━━━━━━━━━━━━┓");printf("\n ┃欢迎使用本系统┃");printf("\n ┏〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓┓"); printf("\n ┃★★★★★★散列法的实验研究★★★★★★┃"); printf("\n ┃【1】. 添加数据信息【2】数据的输出┃"); printf("\n ┃【3】. 建立哈希表(线性再散列) ┃"); printf("\n ┃【4】. 建立哈希表(二次探测再散列) ┃"); printf("\n ┃【5】. 建立哈希表(链地址法) ┃"); printf("\n ┃【6】. 线性再散列法查找┃"); printf("\n ┃【7】. 二次探测再散列法查找┃"); printf("\n ┃【8】. 链地址法查找┃"); printf("\n ┃【0】. 退出程序┃"); printf("\n ┗〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓┛"); printf("\n");printf("\n");printf("请输入一个任务选项>>>");int x;scanf("%d",&x);switch(x){case 1:GetIn (a);break;case 2:GetOut(a);break;case 3:CreateHashTable1(hash1,a,num);break;case 4:CreateHash3(ha,a,num);break;case 5:CreateHashTable2(hash2,a,num);break;case 6:printf("请输入你查找的数据:");scanf("%d",&data);SearchHash1(hash1,data);break;case 7:printf("请输入你查找的数据:");scanf("%d",&data);SearchHash3(ha,data);break;case 8:printf("请输入你查找的数据:");scanf("%d",&data);SearchHash2(hash2,data,num);break;case 0:exit(-1);}}}d.调试分析(1)程序的关键是掌握文件的相关操作、哈希函数的创建和运用、处理冲突的方法等。

散列表的设计与实现-数据结构课程设计报告

散列表的设计与实现-数据结构课程设计报告
{
printf("请输入姓名:\n");
scanf("%s",name);
printf("输出查找的信息:\n");
find2(name);
}
else
printf("输入错误~\n");
}
}
if(select==2)
{
printf("姓名散列结果:\n");
list2();
}
if(select==3)
while(p)
{
printf("%s %s %s\n",p->name,p->address,p->num);
p=p->next;
}
}
}
void list2() {
int i;
node *p;
for(i=0;i<20;i++)
{
p=nam[i]->next;
while(p)
{
printf("%s %s %s\n",p->name,p->address,p->num);
输入1实现查找记录功能,输入2实现姓名散列,输入3实现号码散列,输入4
实现清空记录,输入5实现保存记录,输入6实现退出系统。 Haxi()存储电话号码。
Haxi2()存储姓名。
input()输入节点。
addnode()添加节点。
create()新建节点。
create2()新建节点。
list()显示列表。
newname->next=nam[key2]->next;
nam[key2]->next=newname;

散列表实验报告

散列表实验报告

课程名称:数据结构实验项目:散列表题目:散列表实验一、需求分析1、实验目标掌握散列表的构造方法以及冲突处理方法,实现散列表的运算算法。

2、程序的输入和输出输入:void insertRec(char x[], char y[])输出:void print() {const char space[] = " ";int i, k;for (i = 0; i < N; i++) {k = H(a[i].key);cout << i << ":\t"<< a[i].key << "\t"<< a[i].value << "\t";if (strlen(a[i].key) > 0)cout << "(" << k << ")";cout << endl;}二、概要设计1、数据结构带头节点的线性链表。

主要的操作:查找节点,插入节点,更新节点,打印链表。

2、程序的模块分为两个程序文件。

主要模块如下:void init();void insertRec(char x[], char y[]);int searchRec(char x[]);int deleteRec(char x[]);void print();三、详细设计1、数据结构#include <cstdlib>#include <iostream>using namespace std;const int N = 17; //散列表长struct record { //记录char key[24];char value[24];int deleted;};record a[N]; //散列表int H(char key[]); //散列函数void init();void insertRec(char x[], char y[]);int searchRec(char x[]);int deleteRec(char x[]);void print();int main(int argc, char *argv[]){int i, k;char x[24], y[24];init();cout << "输入要插入的记录: \n";for (i = 0; i < 14; i++) {cin >> x >> y;insertRec(x, y);print();}system("PAUSE");return EXIT_SUCCESS;}void insertRec(char x[], char y[]) { int i, k;i = H(x);while (strlen(a[i].key) > 0) {i++; //线性探测if (i == N) i = 0; //绕回表头}strcpy(a[i].key, x);strcpy(a[i].value, y);}int deleteRec(char x[]) {}int searchRec(char x[]) {}int H(char key[]) {int i = key[0], j = key[1];return (i*i + j*j) % N;}void print() {const char space[] = " "; int i, k;for (i = 0; i < N; i++) {k = H(a[i].key);cout << i << ":\t"<< a[i].key << "\t"<< a[i].value << "\t";if (strlen(a[i].key) > 0)cout << "(" << k << ")"; cout << endl;}}void init() {int i;for (i = 0; i < N; i++) {strcpy(a[i].key, "");strcpy(a[i].value, "");a[i].deleted = 0;}}四、测试结果1、输入autumn 秋天2、输出0:1:2:3:4:5:6:7:8:9:10:11:12:autumn秋天<12>13:14:15:16:。

《散列表的设计与实现》课程设计说明书

《散列表的设计与实现》课程设计说明书

届课程设计《散列表的设计与实现》设计说明书学生姓名学号所属学院信息工程学院专业计算机科学与技术班级计算机指导教师教师职称讲师塔里木大学教务处制目录前言 (1)1.1设计背景和意义 (1)1.1.1数据结构简介 (1)1.1.2选择算法的原因 (1)1.2设计的原理和内容 (1)正文 (1)2.1 设计的目的和意义 (1)2.2 目标和总体方案 (2)2.3 设计方法和内容 (2)2.3.1 硬件环境 (2)2.3.2软件环境 (2)2.3.3设计内容 (3)2.3.4 设计流程图 (3)2.4 设计创新与关键技术 (6)2.5结论 (6)2.5.1存在的问题 (6)2.5.2解决方案 (7)参考文献 (10)程序的设计思想和内容............................. 错误!未定义书签。

3.1程序设计的初始运行环境 .................... 错误!未定义书签。

3.2散列表的初始化............................ 错误!未定义书签。

3.3数据的插入................................ 错误!未定义书签。

3.4数据元素的查找............................ 错误!未定义书签。

3.5数据的删除................................ 错误!未定义书签。

3.6数据的合并................................ 错误!未定义书签。

3.7完成...................................... 错误!未定义书签。

前言1.1设计背景和意义1.1.1数据结构简介数据结构是计算机程序设计的重要理论设计基础,是一门综合性的专业基础科。

数据结构是研究数据之间的相互关系,也即数据的组织形式的一门科学。

它不仅是计算机学科的核心课程,数据结构是计算机存储、组织数据的方式。

山东大学-数据结构实验报告-矩阵与散列表

山东大学-数据结构实验报告-矩阵与散列表

山东大学计算机科学与技术学院数据结构课程实验报告了Input函数和Output函数。

对问题三,仿课本所述,定义Term类作为SparseMatrix类的友元类,包含行、列、值三个要素的成员变量,用Term类的数组实现稀疏矩阵的行主映射存储。

查找行为的实现方式是,找到位于目标元素前一行的最后一个元素,再从这个元素开始向下搜索,直到找到和目标元素同一行但是列数小于目标元素的元素a[k-1],然后决定下一步的行为————插入一个新项Term作为a[k]并将已有元素向后移位,还是修改已存在的项a[k]。

以此原理编写了Store和Retrieve函数,并扩展编写了Input函数和Output函数。

对问题四,仿照课本例子编写了有序链表类SortedChain、开放寻址的散列表类HashTable、基于有序链表链接的散列表类ChainHashTable,并对这三个类分别扩展编写了Output函数。

3.测试结果(测试输入,测试输出)问题一:问题二:上图显示了输入不符合下三角方阵约束时,抛出异常并退出程序。

上图是正常运行的结果。

问题三:普通的输入和输出操作如下:矩阵相加:矩阵转置:问题四:以上图的数据为例。

从346就应该在链表链接的散列表上看到开放寻址解决冲突的例子。

返回开放寻址的输出段,可以看到符合预期的结果:4.实现源代码(程序风格清晰易理解,有充分的注释)/** TridiagonalMatrix.h** Created on: Nov 22, 2015* Author: xudp*/#ifndef TRIDIAGONALMATRIX_H_#define TRIDIAGONALMATRIX_H_#include<iostream>usingnamespace std。

template<class T>class TridiagonalMatrix {public:// 1、创建三对角矩阵类,采用按列映射方式,提供 store 和 retrieve 方法。

散列表实验报告doc

散列表实验报告doc

散列表实验报告doc散列表实验报告篇一:数据结构实验散列表实验报告课程实验报告课程名称:实验项目名称:专业班级:姓名:学号:完成时间:月背景散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构。

也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。

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

在理想情况下,查找、插入、删除操作的时间均为O(1),是一种高效的动态集合结构。

例1:计算机程序设计语言的编译程序需要维护一个符号表,其中元素的关键值为任意字符串,与语言中的标识符对应。

该符号表常采用散列表。

例2:为了节约空间,常常需要把文本文件采用压缩编码方式存储。

LZW是对文本文件进行压缩和解压缩的方法之一,该方法采用了散列。

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

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

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

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

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

基本要求(1)根据输入建立图书名称表,采用散列表实现该表,散列函数选用BKDE 字符串哈希。

(2)数据的输入输出格式:输入分为两部分第一部分,第一行是行数n,n 第二部分,第一行是行数m,m 输出:输出为m行,如果被查的记录存在,则输出"YES",如果不存在则输出"NO"。

测试数据输入:4aansandhellocppaban。

数据结构课设散列表的设计与实现

数据结构课设散列表的设计与实现

#define MAXSIZE 20 //电话薄记录数量#define MAX_SIZE 20 //人名的最大长度#define HASHSIZE 20//定义表长#define SUCCESS 1#define UNSUCCESS —1#define LEN sizeof(HashTable)typedef int Status;typedef char NA[MAX_SIZE];typedef struct //哈希表{NA name;NA tel;NA add;}Record;typedef struct //哈希表{Record *elem[HASHSIZE];//数据元素存储基址int count; //当前数据元素个数int size;//当前容量}HashTable;#include<stdio。

h〉#include〈stdlib.h>#include〈string。

h〉#include ”散列表的设计与实现.h”#include〈iostream.h〉Status eq(NA x,NA y)//关键字比较,相等返回SUCCESS;否则返回UNSUCCESS {if(strcmp(x,y)==0)return SUCCESS;elsereturn UNSUCCESS;}Status NUM_BER; //记录的个数void getin(Record*a) //键盘输入各人的信息{cout〈<”输入要添加的个数:\n”;cin>>NUM_BER;int i;for(i=0;i〈NUM_BER;i++){cout〈〈"请输入第"〈<i+1〈<"个记录的用户名:\n";cin〉>a[i]。

name;cout〈〈”请输入第"<〈i+1<〈"个记录的电话号码:\n";cin>>a[i]。

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

榆林学院14届课程设计《散列表的设计与实现》课程设计说明书学生姓名:学号:院系:信息工程学院专业:计算机科学与技术班级:计14本1指导教师:答辩时间:2015年 12 月 31 日摘要 (1)Abstract (2)第一章绪论 (3)1. 数据结构简介 (3)2. 应用技术领域及范围 (3)3.设计的原理、方法和主要内容 (3)第二章需求分析 (4)1. 任务需求 (4)2. 功能需求 (4)3. 设计目的 (4)4. 设计要求 (4)第三章系统设计 (6)1. 设计思想 (6)2. 实现方法 (6)3. 主要模块 (6)4. 系统功能设计 (6)第四章系统实现及调试 (8)1. 系统功能流程 (8)2. 功能模块实现及调试 (9)总结 (11)参考文献 (11)散列表的设计与实现所涉及到的操作算法都是以链表或顺序表的基本运算作为基础的,此程序通过通讯录实现,包括建立通讯录,添加记录,查询记录,删除记录,显示记录,修改记录。

通过顺序表存储结构实现数据的输入,实现各子程序过程的演示,对异常输入信息报错。

关键字:新建通讯录,添加记录,查询记录,修改记录,删除记录,显示记录,散列表,散列函数,处理冲突AbstractThe design and implementation of the hash table are based on the basic operations of the list or sequence table. This program is implemented by the address book, including the establishment of the address book, adding records, record, delete records, record, modify records. Through sequential table storage structure to achieve data input, to achieve the process of the subroutine, the exception of the input information.Key words: new address book, add records, record, modify records, delete records, display records, hash table, hash function, handling conflict.第一章绪论1. 数据结构简介数据结构是计算机程序设计的重要理论设计基础,它不仅是计算机学科的核心课程,而且成为其他理工专业的热门选修课。

数据结构是指相互之间存在一种或多种特定关系的数据元素的集合。

通常情况下,精心选择的数据结构可以带来更高的运行或者存储效率。

数据结构往往同高效的检索算法和索引技术有关。

在计算机科学中,数据结构是一门研究非数值计算的程序设计问题中计算机的操作对象(数据元素)以及它们之间的关系和运算等的学科,而且确保经过这些运算后所得到的新结构仍然是原来的结构类型。

“数据结构”在计算机科学中是一门综合性的专业基础课。

数据结构是介于数学、计算机硬件和计算机软件三者之间的一门核心课程。

数据结构这一门课的内容不仅是一般程序设计(特别是非数值性程序设计)的基础,而且是设计和实现编译程序、操作系统、数据库系统及其他系统程序的重要基础。

2. 应用技术领域及范围在各个领域,不同的通讯录其功能都是为用户储存信息,查找信息提供方便的有效工具。

一个内容全面、功能先进的通讯录对每个用户来说是一个理想的助手。

现在,我们通过对散列表和基本操作的学习和理解,以及在掌握线性表等基本运算的基础上,实现对线性表操作。

这里我们所做的通讯录则是在数据结构学习之后,利用计算机c程序语言编写的,可以实现数据的新建通讯录,添加记录,查询记录,修改记录,删除记录,显示记录功能的可执行程序。

通过它可以进行对联系对象的姓名、地址、电话号码等的记录与查找。

当然,该程序设计也有不足之处,我们一定会不断地努力去更正完善。

很多涉及通讯录的操作的算法都是以顺序表操作为基础,通过顺序表的建立,初始化,结点添加、查询与删除的演示,方便在学习中更好的理解顺序表结点的添加、查询、删除的过程。

3.设计的原理、方法和主要内容通讯录原理是我们所学的散列表的设计与实现的应用,并且是在数据老师的指导下编写的源程序。

得到了自己所设计的结果。

散列表的方法是通过访问key而直接访问存储的value 值。

它的key - value之间存在一个映射函数,我们可以通过key值和“看不到”的映射函数(散列函数)访问对应的value值。

这加快了查找的速度!存放记录的数组称做散列表。

散列方法不同于顺序查找、二分查找、二叉排序树及B-树上的查找。

它不以关键字的比较为基本操作,采用直接寻址技术(就是说,它是直接通过key映射[映射函数,实现的方式有多种] 到内存地址上去的)。

第二章需求分析1. 任务需求设计散列表通讯录实现电话号码查找系统2. 功能需求1.每个记录需要有存储的数据:姓名、电话、地址;2.从键盘输入各记录,分别以电话号码和用户名为关键字建立散列表;3.采用一定的方法解决冲突;4.查找并显示给定电话号码的记录;5.查找并显示给定用户名的记录。

6. 【进一步完成内容】1)系统功能的完善;2)设计不同的散列函数,比较冲突率;3)在散列函数确定的前提下,尝试各种不同类型处理冲突的方法,考察平均查找长度的变化。

3. 设计目的课程设计是《数据结构》课程教学必不可缺的一个重要环节,它可加深学生对该课程所学内容的进一步的理解与巩固,是将计算机课程与实际问题相联接的关键步骤。

通过课程设计,能够提高学生分析问题、解决问题,从而运用所学知识解决实际问题的能力,因而必须给予足够的重视。

4. 设计要求1.明确课程设计任务,复习与查阅有关资料。

2.按要求完成课程设计内容,课程设计报告要求文字和图工整、思路清楚、正确。

3.应用程序应具有一定的可用性:(1)凡等候用户输入时,给出足够的提示信息,如“Please Select(1—3):”提示用户选择。

(2)格式明显易懂,配上适当的颜色、声音等辅助效果,能方便地改正输入时的错误,使用户感到方便、好用。

(3)有联机求助功能。

用户能直接从系统得到必要的提示,不查手册也能解决一些疑难。

4.程序具有一定的健壮性,不会因为用户的输入错误引起程序运行错误而中断执行:(1)对输入值的类型、大小范围、字符串的长度等,进行正确性检查,对不合法的输入值给出出错信息,指出错误类型,等待重新输入。

(2)当可能的回答有多种时,应允许输入任何一种回答。

(3)对删除数据应给出警告。

第三章系统设计1. 设计思想要用散列表设计实现电话号码查询系统,对存入的联系人的名字电话以及地址进行存储,并在输入电话号码或姓名后得出此记录的所有信息,要求有菜单界面和清屏功能.首先,此程序,多次用到哈希函数,此处先用除留余数法对折叠后的数构造哈希函数,再用二次探测再散列法建立冲突处理函数解决冲突,再以电话号码和姓名为关键字建立散列表(若哈西地址冲突进行冲突处理),在此之前,必须先用一系列输出函数输出一个菜单.整个程序的设计思路到此结束。

2. 实现方法根据系统功能要求,可以将实现方法分为以下步骤:(1)应用系统分析,建立该系统的功能模块框图以及界面的组织和设计;(2)分析系统中的各个数据及它们之间的关系;(3)根据问题描述,设计系统的类层次;(4)完成各个函数的声明;(5)完成各个成员函数的定义;(6)完成系统的应用模块;(7)功能调试;(8)完成系统总结报告。

3. 主要模块键盘输入各人的信息:void getin();显示输入的用户信息:void ShowInformation() ;除留余数法构造哈希函数:int Hash1();构造把字符串转换成整型数哈希函数:int Hash2();冲突处理函数:Status collision();以姓名为关键字建表:void CreateHash1();以姓名为关键字查表:void SearchHash1();以电话号码为关键字建表:void CreateHash2();以电话号码为关键字查表:void SearchHash2();输出菜单函数:int main()。

4. 系统功能设计定义电话本记录数量(MAXSIZE)、表长(HASHSIZE)、姓名长度(MAX_SIZE)及结构体typedef struct的内容,构造两个哈希函数hash1和hash2.功能示意图如下:第四章系统实现及调试1. 系统功能流程增加系统功能如下: 添加用户信息;读取所有用户信息;以姓名建立哈希表;以电话号码建立哈希表;查找并显示给定用户名的记录;查找并显示给定电话号码的记录;清屏以及保存功能;处理流程示意图如下:图2 处理流程示意图2. 功能模块实现及调试1)运用main函数输出电话本信息系统的整体界面,在调试运行后如下:图3 调式运行图2)利用添加功能void getin(Record* a)实现用户信息的录入,在调试运行后如下:图4 用户信息录入图3)利用哈希函数CREATEHASH1.2来构造哈希表并用Status collision函数的相应功能来查找并解决冲突:图5 解决冲突和构造哈希表图4)利用void SearchHash1(HashTable* H,int &c)在通讯录里查找姓名关键字,若查找成功,显示信息,c用来记录冲突次数,查找成功时显示冲突次数:图6 查找姓名关键字的结果和冲突次数截图总结通过这一次的课程设计,我对软件编程的基础数据结构有了更好的理解,知道了数据结构在编程中的作用。

同时,也增加了我对学习软件编程的兴趣,为以后的学习打下了好的基础。

当然,也加深了我对C语言的理解,懂得了C语言编程的一些重要的知识。

对于数据结构和算法,虽然我目前的理解还不深,但是,这次课程设计后,我相信我以后慢慢地会了解的更深。

在编写程序设计散列表的设计和应用的代码中,遇到了一些错误,最终,经过我上网查询才解决了。

在实际操作过程中犯的一些错误还会有意外的收获,感觉很有意思。

在具体操作中对这学期所学的数据结构的理论知识得到巩固,达到设计的基本目的,也发现自己的不足之处,在以后的上机中应更加注意,同时体会到算法应具有的语句简洁,简单易懂,可读性高,使用灵活,执行效率高等特点。

计算机编程的学习,主要靠自己的自学,不懂就得去问,找到解决的方法。

参考文献[1].严蔚敏. 《数据结构(C语言版)》. 清华大学出版社. 2002[2].李庆华.刘秀娟.王春光函数递归调用问题的简化读程方法 -长春大学学报2003,13(3)[3].苏仕民.数据结构课程设计北京:机械工业出版社.2005[4].Sartaj Sahni. Data Structure, Algorithms, and Application in C++. The McGraw-Hill Company Inc.1998[M] (第一版) (数据结构、算法与应用——C++语言描述.北京:机械工业出版社.1999[5].Willan Ford,Willian Topp. Data Structures with C++. New Jersey:Prentice Hall Inc, Adivision Simon & Schuster Company,1996[M] (第一版) (数据结构——C++语言描述.北京:清华大学出版社,1997[6].徐孝凯.数据结构实用教程(C/C++描述)[M]. (第一版)北京:清华大学出版社.1999[7].程杰.大话数据结构北京:清华大学出版社.2011。

相关文档
最新文档