哈希表与哈希函数 C实现

<pre name="code" class="cpp"><pre name="code" class="cpp"><pre name="code" class="cpp"> <strong>散列表</strong>(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中
一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。
    给定表M,存在函数f(key),对任意给定的关键字值key,代入函数后若能得到包含该关键字的记录在表中的地址,则称表M为<strong>哈希(Hash)表</strong>,
函数f(key)为<strong>哈希(Hash) 函数</strong>。

哈希表就是一维数组,数组元素是一个结构体
	:结构体有一个节点指针元素,可以有一个数据域,也可以有多个数据域,也可以没有

 简单的说
哈希表:hash_table  =  顺序结构+链式结构

<strong>冲突:</strong>    元素x、y、z 分别 % 上 P(默认哈希表长度)后相等,即应该存放在相同下标下
<strong>解决办法:</strong>把y插入到一个节点中,该节点悬挂到下标为x%P的数组元素下面,z悬挂到y下面。

//下面给出哈希表的实现、插入以及打印代码:
#include<iostream>
using namespace std;

#define P 7          // 哈希表默认表长
#define $ -1         // 默认初始化的值
#define ElemType int // 值类型

typedef struct bucket_node      // 节点类型
{
	ElemType data[3];
	struct bucket_node *next;   // 每个节点能存放3个数据和一个指向另一个节点的指针
}bucket_node;

typedef bucket_node hash_table[P];   // 定义哈希表(实际就是一个数组)

/*初始化哈希表(数组)元素 */
void init_bucket_node(hash_table &ht, int i)
{
	memset(&ht[i], $, sizeof(ElemType)*3);
	ht[i].next = 0;
}

/* 初始化哈希表 */
void init_hash_table(hash_table &ht)
{
	for(int i = 0; i<P; ++i)
		init_bucket_node(ht, i);
}

/* 哈希函数,得到元素x应当插入到哈希表的哪个下标 */
int hash(ElemType x)
{
	return x % P;
}

/* 把元素x 插入到哈希表ht中 */
int insert_new_element(hash_table &ht, ElemType x)
{
	int index = hash(x);         //得到元素x应当插入到哈希表的哪个下标
	for(bucket_node* p = &ht[index],*q = NULL; NULL!=p; q=p,p=p->next)
	{										// 节点指针p 指向ht[index]节点
		if(NULL != p->next)                 // 如果p->next == NULL,说明p所指节点的三个数据已经插满
			continue;						 // 则p指向下一个节点

		for(int i = 0; i<3; ++i)
		{
			if($ == p->data[i])             // 如果某个位置等于$,说明该位置为空,把x插入并返回
			{
				p->data[i] = x;
				return 0;
			}
		}
	}
	if(NULL == p)       // 如果 p == NULL,说明最后一个节点刚好插满,需要另外开辟一个节点的内存
	{
		bucket_node * s = new bucket_node;
		memset(s, $, sizeof(ElemType)*3);     // 初始化刚开辟的内存
		s->next = NULL;
		s->data[0] = x;                       // x 放入该节点的第一个位置
		q->next = s;                          // 把s 挂到最后一个节点的下面
		return 0;
	}
	return -1;     // 如果没有在现有节点下找到位置,并且开辟节点也失败的话,x 就真的不能插入了
}

/* 打印哈希表 */
void show_hash_table(hash_table &ht)
{
	bucket_node* p = NULL;
	for(int i = 0; i<P; ++i)     // 从第一个哈希表元素开始打印,知道最后一个元素
	{
		cout<<"ht["<<i<<"]"<<" :  ";
		for(p=&ht[i]; NULL!=p; p=p->next)   // 打印下标为i的哈希表元素及该位置所链接的节点
		{
			for( int k = 0; 3>k && $!=p->data[k]; ++k) // p->data[k] != $ ,说明该位置不空,则打印
			{
				cout<<p->data[k]<<" ";
			}
		}
		cout<<endl;
	}
}
//下面是测试代码: Main.cpp

void main()
{
	hash_table ht;

	ElemType ar[] = {0,7,14,21,28,59,35,42,5,9,3,6,13,52,64};   // 测试数组

	init_hash_table(ht);       // 初始化哈希表

	for(int i = 0; i<sizeof(ar)/sizeof(*ar); ++i)
		insert_new_element(ht, ar[i]);        // 数组元素依次插入哈希表

	show_hash_table(ht);                  // 打印哈希表

	cout<<"Over"<<endl;

}

<pre name="code" class="cpp">如果数据较多(足够多)的话,插入的元素应该均匀地分布在哈希表中,也就是每个节点元素后面的链长度应该相等.






版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-10 07:19:07

哈希表与哈希函数 C实现的相关文章

哈希表和哈希函数

一.哈希表 通过记录的存储位置和它的关键字之间建立一个确定的对应关系 f  以及处理冲突的方法,使得每个关键字和结构中一个唯一的存储位置相对应.这样对于关键字 K  根据对应关系 f  ,就可以找到存储在 f(K) .称这种对应关系f 为 哈希函数,按照这种方法建立的表称为哈希表. 1.1 原理: 通过记录的存储位置和它的关键字之间建立一个确定的对应关系 f ,使得每个关键字和结构中一个唯一的存储位置相对应.这样对于关键字 K  根据对应关系 f  ,就可以找到存储在 f(K) .称这种对应关系

哈希函数和哈希表综述 (转)

哈希表及哈希函数研究综述 摘要 随着信息化水平的不断提高,数据已经取代计算成为了信息计算的中心,对存储的需求不断提高信息量呈现爆炸式增长趋势,存储已经成为急需提高的瓶颈.哈希表作为海量信息存储的有效方式,本文详细介绍了哈希表的设计.冲突解决方案以及动态哈希表.另外针对哈希函数在相似性匹配.图片检索.分布式缓存和密码学等领域的应用做了简短得介绍 哈希经过这么多年的发展,出现了大量高性能的哈希函数和哈希表.本文通过介绍各种不同的哈希函数的设计原理以及不同的哈希表实现,旨在帮助读者在实际应用中,根据问

哈希表

哈希表支持的一种最有效的检索方法:散列. 由于计算哈希值和在数组中进行索引都只消耗固定时间,因此哈希表的最大亮点在于他是一种运行时间在常量级的检索方法. 哈希表主要有两种: 1.链式哈希表:将数据存储在桶中的哈希表,每个桶里面都是一个链表,且链表的容量随着冲突的增大而增大.(换句话说就是如果有冲突,会在桶中的链表加上一个存储的值) 2.开地址哈希表:将数据存在表本身,而不是在桶中,他通过各种探查方法来避免冲突. 解决冲突: 不管在以上那种哈希表中,我们的目标是尽可能均匀的分配表中的元素.所以我们

9. 蛤蟆的数据结构进阶九哈希表实现

9. 蛤蟆的数据结构进阶九哈希表实现 本篇名言:"人们所努力追求的庸俗的目标 --我总觉得都是可鄙的. -- 爱因思坦" 上篇我们看了哈希表的相关定义和概念,这篇来看下如何来实现. 欢迎转载,转载请标明出处:http://blog.csdn.net/notbaron/article/details/47362781 1.  代码实现 1.1             Main 函数定义哈希元素数组 10个元素. 定义哈希表变量. 调用InitHashTable构造一个空的哈希表. 然后循

Nginx 哈希表结构 ngx_hash_t

概述 关于哈希表的基本知识在前面的文章<数据结构-哈希表>已作介绍.哈希表结合了数组和链表的特点,使其寻址.插入以及删除操作更加方便.哈希表的过程是将关键字通过某种哈希函数映射到相应的哈希表位置,即对应的哈希值所在哈希表的位置.但是会出现多个关键字映射相同位置的情况导致冲突问题,为了解决这种情况,哈希表使用两个可选择的方法:拉链法 和 开放寻址法. Nginx 的哈希表中使用开放寻址来解决冲突问题,为了处理字符串,Nginx 还实现了支持通配符操作的相关函数,下面对 Nginx 中哈希表的源码

浅谈算法和数据结构: 十一 哈希表

在前面的系列文章中,依次介绍了基于无序列表的顺序查找,基于有序数组的二分查找,平衡查找树,以及红黑树,下图是他们在平均以及最差情况下的时间复杂度: 可以看到在时间复杂度上,红黑树在平均情况下插入,查找以及删除上都达到了lgN的时间复杂度. 那么有没有查找效率更高的数据结构呢,答案就是本文接下来要介绍了散列表,也叫哈希表(Hash Table) 什么是哈希表 哈希表就是一种以 键-值(key-indexed) 存储数据的结构,我们只要输入待查找的值即key,即可查找到其对应的值. 哈希的思路很简单

哈希表入门讲解

散列表(Hash table,也叫哈希表),是根据键(Key)而直接访问在内存存储位置的数据结构.也就是说,它通过计算一个关于键值的函数,将所需查询的数据映射到表中一个位置来访问记录,这加快了查找速度.这个映射函数称做散列函数,存放记录的数组称做散列表. 一个通俗的例子是,为了查找电话簿中某人的号码,可以创建一个按照人名首字母顺序排列的表(即建立人名{\displaystyle x}到首字母{\displaystyle F(x)}的一个函数关系),在首字母为W的表中查找"王"姓的电话号

上古时代 Objective-C 中哈希表的实现

因为 ObjC 的 runtime 只能在 Mac OS 下才能编译,所以文章中的代码都是在 Mac OS,也就是 x86_64 架构下运行的,对于在 arm64 中运行的代码会特别说明. 写在前面 文章会介绍上古时代 Objective-C 哈希表,也就是 NXHashTable : NXHashTable 的实现 NXHashTable 的性能分析 NXHashTable 的作用 NXHashTable 的实现有着将近 30 年的历史,不过仍然作为重要的底层数据结构存储整个应用中的类. 文中

【数据结构】哈希表的线性探测算法

构造哈希表常用的方法是: 除留余数法--取关键值被某个不大于散列表长m的数p除后的所得的余数为散列地址.HashKey= Key % P. 直接定址法--取关键字的某个线性函数为散列地址HashKey= Key 或 HashKey= A*Key + BA.B为常数. 我在这里主要使用一下除留余数法Hash(key) =Key%P,(P这里是哈希表的长度)p最好是素数考虑降低哈希冲突的原因,我并没有在这上面过于追究此处哈希表长度10,见线性探测图. 哈希表经常遇到的一个问题就是哈希冲突. 哈希冲突