热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

数据结构与算法实验报告哈希表的设计

 

数据结构与算法实验报告

实验

实验四 哈希表设计

学院

 

专业(班级)

 

姓名

 

学号

 

教师

 

实验四 哈希表设计

 

1实验目的

1.熟悉有关哈希表的基本概念;

2.熟悉构造哈希表的方法;

3.掌握哈希冲突的处理方法。

2实验要求

1.根据教材给出的方法,自己设计哈希表的存储结构;

2.根据教材给出的方法,自己设计哈希函数和处理冲突的方法;

3.实现哈希表的基本操作,完成哈希表的查找过程。

3实验环境

硬件平台:计算机CPU 主频2.0G以上;内存128兆以上;

软件平台:Windows2003或以上版本,Visual C++6.0。

4实验内容

1.根据教材给出的方法,选择一种哈希函数的设计方法和处理冲突的方法,设计一种哈希表;输入一批关键字集合,建立哈希表。

2.实现哈希表的基本操作:创建、销毁、取元素个数、置空、判空、赋值、取值、插入、删除等。

3.完成哈希表的查找过程。

5实验步骤

  • 需求分析:
  1. 本实验要求建立哈希表,并对哈希表进行增删查操作。
  2. 不经历任何比较,一次存取便能得到所查记录,因此在记录的存储位置和关键字之间建立一个确定的对应关系,使每个关键字和结构中一个唯一的存储位置相对应。对应的建立一个这样的哈希函数。
  3. 对不同的关键字可能得到同一散列地址,即key1!=key2,但是f(key1)=f(key2)。这就产生了冲突,因此需要处理冲突的函数。
  4. 根据哈希函数和处理冲突的方法将一组关键字映像到有限的连续地址上,便建立了哈希表。查找时也根据哈希函数和处理冲突方法,找到关键字地址,找到关键字。

 

  • 概要设计:

哈希表的存储结构:

typedef struct {

ElemType *elem;

int count;

int sizeindex;

}HashTable;//哈希表的结构

 

int hashsize[]={997,...}//哈希表容量递增表,一个合适的素数序列

 

Status Hash(int K){

return K%m;

}//哈希函数(除留余数法)

 

void collision(int *p,int d)//处理冲突函数(我在本次实验中使用了两种方法,开放定址法和链地址法)

 

Status SearchHash(HashTable H,KeyType K,int &p,int &c){}

// 在开放定址哈希表H中查找关键码为K的元素,若查找成功,以p指示待查数据。

 

Status InsertHash(HashTable &H,ElemType e){}

//查找不成功时插入数据元素e到开放定址哈希表H中,并返回OK;若冲突次数过大,则重建哈希表。

 

三.程序思想

1.哈希函数:生成映射地址。

2.处理冲突函数:对冲突的关键字进行处理。

3.插入函数:插入关键字,先计算关键字的映射地址,然后在相应的地址插入,如果冲突,则利用处理冲突函数查找空位插入。

4.查找函数:先计算关键字的地址,再判断是否冲突,再到散列表中查找。

 

四.功能流程图

数据结构与算法实验报告---哈希表的设计

                                                   程序流程

数据结构与算法实验报告---哈希表的设计

                                           哈希表的插入

数据结构与算法实验报告---哈希表的设计

                                             哈希表的查找

五.程序运行截图:

数据结构与算法实验报告---哈希表的设计

                                                                 界面

数据结构与算法实验报告---哈希表的设计

                         

数据结构与算法实验报告---哈希表的设计

                                                      哈希表的查找

数据结构与算法实验报告---哈希表的设计

                                         哈希表的创建(链地址法)

数据结构与算法实验报告---哈希表的设计

数据结构与算法实验报告---哈希表的设计

                                     哈希表的查找(链地址法) 六.程序源代码:

 

#include 
#include 
#include 
#include
#include
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
#define SUCCESS 1
#define UNSUCCESS 0
#define DUPLICATE -1
#define NULLKEY 0
using namespace std;
typedef int KeyType;
typedef int Status;
int m=0;
int N;
int hashsize[]={11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997};
typedef struct{
	KeyType key;
}ElemType;

struct ElemType1{
	KeyType key;
	struct ElemType1*next;
};

typedef struct HashTable2{
	ElemType1 **elem;//二级指针型向量,采用动态分配空间大小
	int count;//当前的头指针向量的元素
	int hashindex;//hashsize[H.hashindex]为当前容量
}HashTable1;

typedef struct {
	ElemType *elem;
	int count;
	int sizeindex;
}HashTable;

int SearchHashTable1(ElemType1 *L, KeyType K, ElemType1 *&v){
	ElemType1 *s = NULL;
	s = (ElemType1*)malloc(sizeof(ElemType1));
	s->key = K;
	if (!L->next){//一开始为空,插入一个元素
		s->next = L->next;
		L->next = s;
		v = s;
		return 0;
	}
	else{
		ElemType1* p = L->next;
		ElemType1 *q = L;
		while (p&&p->key != K){
			q = p;
			p = p->next;
		}
		if (p&&p->key == K){
			v = p;
			return 1;//找到了数据元素
		}
 
		else{//插入一个数据,此时p为空,需要她的前驱指针q指向最后一个元素,采用尾插法插入元素
			s->next = q->next;
			q->next = s;
			v = s;
			return 0;
		}
	}
 
}

Status Hash(int K){
	return K%m;
}//哈希函数 

void InitHashTable1(HashTable1 &H){
	H.count = 0;
	m = hashsize[0];
	H.elem = (ElemType1**)malloc(m*sizeof(ElemType1*));
	for (int i = 0; i next = NULL;
	}
}

ElemType1* SearchHashTable1(HashTable1 H, KeyType K, int &p){
	p = Hash(K);//p为根据关键字计算的处的头结点所在的位置,关键
	ElemType1 *head = H.elem[p];//记下头结点,关键字记录肯定在以head为头结点的单链表中
	return head;
}

void TraverseHashTable1(HashTable1 H){
	ElemType1 *p = NULL, *q = NULL;
	for (int i = 0; i next){//头结点不空
			printf("\n进入了链表,地址为%d:\n",i);
			q = p->next;//指向首节点
			while (q){
				printf("%d->", q->key);
				q = q->next;
			}
		}
	}
	printf("\n");
}

ElemType1* InsertHashTable1(HashTable1&H, ElemType1 e){
	int p = 0;//为插入的位置
	ElemType1*v = NULL;
	ElemType1*head = SearchHashTable1(H, e.key, p);//找到数据项e应该插入的头结点所在的链表
	//SearchHashTableLinkListElemType;
	SearchHashTable1(head, e.key, v);//动态查找链表
	return v;//返回这个结点,不管找没找到,找到了返回,没找到会自动插入这个元素也返回
	//在以head为头结点的链表中查找e.key关键字的元素
}



Status InitHash(HashTable &H){
	H.count=0;
	H.sizeindex=0;
	m=hashsize[0];
	H.elem=(ElemType *)malloc(m*sizeof(ElemType));
	if(!(H.elem))
	exit(0);
	for(int i=0;ikey!=NULLKEY)
	*p++=*((*H).elem+i);
	(*H).count=0;
	(*H).sizeindex++;
	m=hashsize[(*H).sizeindex];
	p=(ElemType *)realloc((*H).elem,m*sizeof(ElemType));
	if(!p)
	exit(0);
	(*H).elem=p;
	for(i=0;i%d-->地址-->%d\n",r.key,p);
}//打印函数 

void mainview_user( )            //界面函数
{	HashTable h;
	HashTable1 h1; 
	int j,p,x;
	int l=1000;
	ElemType r[N];
	ElemType1 r1[l];
	KeyType k;
	InitHash(h);
	InitHashTable1(h1); 
	int c; 
	while(1)
	{
		system("CLS");  //清除屏幕函数
		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("      |********0   退出系统***********|\n");
		printf("     ------------------------------------\n");
		printf("\n");
		
		printf("请选择:");
		scanf("%d",&c);
		switch(c)
		{
		case 1: {
			printf("按哈希表地址顺序遍历哈希表:\n");
			TraverseHash(h,print);
			break;
		}
		case 2: {
			printf("请输入要插入的关键字:");
			scanf("%d",&k); 
			j=Find(h,k,&p);
			while(1){
				if(j==SUCCESS){
					printf("表中有该元素请重新输入:");
					scanf("%d",&k); 
					
					j=Find(h,k,&p);
				}
				else break;
			} 
			r[N].key=k;
			j=InsertHash(&h,r[N]);
			if(j==0)
			j=InsertHash(&h,r[N]);
			printf("插入成功\n");
			TraverseHash(h,print);
			N+=1;
			break; 
		}
		case 3: {
			printf("请输入要输入的关键字数目:");
			scanf("%d",&N);
			int j;
			printf("请输入关键字:"); 
			for(int i=0;inext){//头结点不空
			printf("\n进入了链表,地址为%d:\n",Hash(k));
			t = q->next;//指向首节点
			while (t){
				printf("%d->", t->key);
				if(t->key==k){
					printf(" 找到了\n");
					break;
				}
				 
				t= t->next;
			}
			printf("没找到\n");
		}
			else printf("没找到\n");
			break;
		}	
		case 0: {
			    DestroyHash(h);
				return;
				 }
		default:printf("输入错误,请重新输入!\n");fflush(stdin);  
		}
		printf("\n\n");
		
		system("PAUSE");
	}
}

int main(){
	mainview_user();
}

推荐阅读
  • eclipse学习(第三章:ssh中的Hibernate)——11.Hibernate的缓存(2级缓存,get和load)
    本文介绍了eclipse学习中的第三章内容,主要讲解了ssh中的Hibernate的缓存,包括2级缓存和get方法、load方法的区别。文章还涉及了项目实践和相关知识点的讲解。 ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • 本文介绍了iOS数据库Sqlite的SQL语句分类和常见约束关键字。SQL语句分为DDL、DML和DQL三种类型,其中DDL语句用于定义、删除和修改数据表,关键字包括create、drop和alter。常见约束关键字包括if not exists、if exists、primary key、autoincrement、not null和default。此外,还介绍了常见的数据库数据类型,包括integer、text和real。 ... [详细]
  • 云原生边缘计算之KubeEdge简介及功能特点
    本文介绍了云原生边缘计算中的KubeEdge系统,该系统是一个开源系统,用于将容器化应用程序编排功能扩展到Edge的主机。它基于Kubernetes构建,并为网络应用程序提供基础架构支持。同时,KubeEdge具有离线模式、基于Kubernetes的节点、群集、应用程序和设备管理、资源优化等特点。此外,KubeEdge还支持跨平台工作,在私有、公共和混合云中都可以运行。同时,KubeEdge还提供数据管理和数据分析管道引擎的支持。最后,本文还介绍了KubeEdge系统生成证书的方法。 ... [详细]
  • SpringBoot uri统一权限管理的实现方法及步骤详解
    本文详细介绍了SpringBoot中实现uri统一权限管理的方法,包括表结构定义、自动统计URI并自动删除脏数据、程序启动加载等步骤。通过该方法可以提高系统的安全性,实现对系统任意接口的权限拦截验证。 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • 本文介绍了Redis的基础数据结构string的应用场景,并以面试的形式进行问答讲解,帮助读者更好地理解和应用Redis。同时,描述了一位面试者的心理状态和面试官的行为。 ... [详细]
  • C# 7.0 新特性:基于Tuple的“多”返回值方法
    本文介绍了C# 7.0中基于Tuple的“多”返回值方法的使用。通过对C# 6.0及更早版本的做法进行回顾,提出了问题:如何使一个方法可返回多个返回值。然后详细介绍了C# 7.0中使用Tuple的写法,并给出了示例代码。最后,总结了该新特性的优点。 ... [详细]
  • 本文详细介绍了Spring的JdbcTemplate的使用方法,包括执行存储过程、存储函数的call()方法,执行任何SQL语句的execute()方法,单个更新和批量更新的update()和batchUpdate()方法,以及单查和列表查询的query()和queryForXXX()方法。提供了经过测试的API供使用。 ... [详细]
  • Python SQLAlchemy库的使用方法详解
    本文详细介绍了Python中使用SQLAlchemy库的方法。首先对SQLAlchemy进行了简介,包括其定义、适用的数据库类型等。然后讨论了SQLAlchemy提供的两种主要使用模式,即SQL表达式语言和ORM。针对不同的需求,给出了选择哪种模式的建议。最后,介绍了连接数据库的方法,包括创建SQLAlchemy引擎和执行SQL语句的接口。 ... [详细]
  • 先看官方文档TheJavaTutorialshavebeenwrittenforJDK8.Examplesandpracticesdescribedinthispagedontta ... [详细]
  • JDK源码学习之HashTable(附带面试题)的学习笔记
    本文介绍了JDK源码学习之HashTable(附带面试题)的学习笔记,包括HashTable的定义、数据类型、与HashMap的关系和区别。文章提供了干货,并附带了其他相关主题的学习笔记。 ... [详细]
  • 本文介绍了一种轻巧方便的工具——集算器,通过使用集算器可以将文本日志变成结构化数据,然后可以使用SQL式查询。集算器利用集算语言的优点,将日志内容结构化为数据表结构,SPL支持直接对结构化的文件进行SQL查询,不再需要安装配置第三方数据库软件。本文还详细介绍了具体的实施过程。 ... [详细]
  • 本文讨论了使用差分约束系统求解House Man跳跃问题的思路与方法。给定一组不同高度,要求从最低点跳跃到最高点,每次跳跃的距离不超过D,并且不能改变给定的顺序。通过建立差分约束系统,将问题转化为图的建立和查询距离的问题。文章详细介绍了建立约束条件的方法,并使用SPFA算法判环并输出结果。同时还讨论了建边方向和跳跃顺序的关系。 ... [详细]
  • 本文介绍了为什么要使用多进程处理TCP服务端,多进程的好处包括可靠性高和处理大量数据时速度快。然而,多进程不能共享进程空间,因此有一些变量不能共享。文章还提供了使用多进程实现TCP服务端的代码,并对代码进行了详细注释。 ... [详细]
author-avatar
手机用户2502909065
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有