ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Hash哈希表的全新理解

2021-11-23 20:33:16  阅读:165  来源: 互联网

标签:Node Hash 哈希 int 全新 地址 key


一、Hash哈希表

无论是栈、队列、还是顺序表等线性结构中,记录的关键字和存储位置之间都不存在一 一对应的关系。在查找记录的时候,则需要对关键字进行逐一比对,过程繁琐,查找效率低。
哈希表是一种高效的查找结构,它的出现很好地解决了这个问题,接下来让我们逐步深入学习。

二、哈希函数

哈希函数是哈希表的灵魂,正因为它的存在,哈希表才完成了从记录关键字到存储位置的一一映射关系。类比y=f(x),存储位置作为因变量是由自变量关键字经过某种函数关系计算而得的。

哈希函数的构造方法:

  1. 直接定址法(y=x):不作变换,直接使用关键字作为哈希地址。
  2. 除留余数法(y=x%a,其中a为常数)
  3. 数字分析法:在关键字中选择分布均匀的位数作为哈希地址(这种方法观察主观选择,与函数无关)
  4. 折叠法
  5. 平方取中法

三、冲突以及处理冲突的方法

首先什么叫冲突?
我们都知道想y=x^2,当y=1时方程有两个解1或者-1。可是如果“1”代表的是唯一的存储地址1,那么这时候究竟是存放“1”还是“-1”呢?(冲突,也就这样产生了)
想要解决冲突就是要解决两个解如何存放的问题(一山不能容二虎)。

  • 链地址法:

平时操场集合的时候,前面排列着各个班的班牌(有且只有一个),每个班都不止一位同学,如何大家都站在班牌那,这就发生了冲突,所以该如何站呢?
很简单,以班牌为地址,同班同学在同一列,逐一向后排列即可。

同样的道理,如果我们能在存储地址1的下方放置另一个解“-1”,依此类推,那冲突的问题就解决了。

  • 开放地址法:
    既然哈希函数可以实现记录关键字和存储位置的一一对应,那我们直接可以新建一个处理冲突的函数(y=x^2-1),这样子,实现了多个解发生冲突的时候,可以错开存放。
    根据所选的冲突函数不同,又分为线性探测法二次探测法(y=x^(2) -a ^(2))

四、哈希表的实现

根据不同的处理冲突的方法,哈希表可以分成两类链地址哈希表开放定址哈希表
(本次主要介绍链地址哈希表,下一讲再介绍开放定址哈希表)

链地址哈希表类型定义:

 typedef struct {
	KeyType key;	//KeyType为新定义类型,方便多种关键字转换 
}RcdType; //记录的结构
typedef struct Node {
	RcdType r;
	struct Node *next;
}Node;	//结点的结构
typedef struct {
	Node **rcd;
	int size;
	int count;
	int (*hash)(KeyType key,int size);//函数指针,可以指向整形,含有两个参数的函数
}Hash;	//哈希表的结构

链地址哈初始化:

//链地址哈希表初始化 
Status InitHash (Hash &H,int size,int (*hash)(int,int)) { //Status 认为定义类型,方便多种类型间转换 
	H.rcd = (Node**)malloc(size*sizeof(Node*));
	if (NULL==H.rcd) {
		return ERROR;
	}
	else {
		for (int i=0;i<size;i++) H.rcd[i] =NULL;	//注意区分H.rcd=NULL;
		H.size = size;
		H.count = ERROR;
		H.hash = hash;
		return ERROR;
	}
}

查找记录:

Node * SearchHash(Hash &H,int key) {
	//使用哈希函数 
	int h = hash(key,H.size);
	Node *p ;
	for (p = H.rcd[h];p!=NULL;p = p->next) {
		if (p->r.key==key) return p;
	}
	return NULL;
}

在表头插入记录:

Status InsertHash (Hash &H,RcdType e) {
	if (SearchHash(H,e.key)==NULL) {
		int h = hash(e.key,H.size);
		Node *p ;
		p->r = e;
		p->next = H.rcd[h];
		H.rcd[h] = p;
		H.count++;		//成功插入后,哈希表内记录数+1;
		return OK;
	} 
	else {
		return FALSE;
	} 
} 

删除记录:

Status  DeleteHash (Hash &H,int key,RcdType &e) {
	Node *p = SearchHash(H,e.key);
	if (p==NULL) {
		return 0; 
	} 
	else {
		key = p->r.key;
		int h = hash(e.key,H.size);
		Node *pr;
		while (pr->next!=p) {
			pr = pr->next;
		}
		pr = p->next;
		free(p);
		H.count--;
		return key;
	}
}

标签:Node,Hash,哈希,int,全新,地址,key
来源: https://blog.csdn.net/m0_54385790/article/details/121500565

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有