8--哈希表Hash的相关操作

哈希表(Hash table)是一种数据结构用于实现键值对的存储和查找。其中直接地址法、数字分析法、平方取中法、折叠法、除留余数法、随机数法都可以作为哈希表的散列函数。

直接地址法是唯一一个不会产生冲突的方法,因为它是线性的,每一个数都有对应的地址,所有就不会产生冲突,但是空间利用率低,它是典型的用空间换时间。而除留余数法是最常用的一种方法。

哈希表的查找、插入和删除操作的时间复杂度通常为O(1),但在极端情况下,可能会出现冲突(多个键映射到同一个索引位置),这时需要解决冲突的方法,比如开地址法、链地址法、再散列法(双散列函数法)、建立一个公共溢出区。

开地址法中又包含了线性探测法(常用)、二次探测法、伪随机探测法。

线性探测法:下一个下一个

二次探测法:左一个右一个(一直循环直到找到空位置)

伪随机探测法:生成随机数,随机存储。每次都得从头遍历,不建议使用

此处我们就用除留余数法和开地址法中的线性探测法来实现哈希表,代码如下:

#include<stdio.h>

#define NONE -1 //将哈希表内初始成-1
#define p 13 //p一般取小于等于m且为质数
#define m 16 //哈希表的长度

//定义Hash结构体
typedef struct Hash
{
	int key;//关键字项;
	//InfoType otherinfo;//其他数据项
}Hash, HashTable[m]; //定义了一个长度为m的Hash数组

//初始化哈希表
void InitHashTable(HashTable  ht)
{
	for (int i = 0; i < m; i++)
	{
		ht[i].key = NONE;
	}
}

//将关键字映射到哈希表的索引位置
//得到key对p取模的结果
static int H(int key)
{
	return key % p;
}

//将key插入到哈希表ht中,成功返回true,失败返回false;
bool Insert(HashTable ht, int key)
{
	int hi = H(key);//得到key的哈希值;

	//当前哈希表没有被使用,将key直接存储;
	if (ht[hi].key == NONE)
	{
		ht[hi].key = key;
		return true;
	}
	
	else//在其他地方找合适的位置,使用线性探测法;
	{
		int i = (hi + 1) % m;//新的位置
		while (i != hi)
		{
			if (ht[i].key == NONE)
			{
				ht[i].key = key;
				return true;
			}
			i = (i + 1) % m;//更新i的位置,即向后移动一个位置
		}
		return false;
	}
}

//在哈希表中查找key,找到返回下标,失败返回-1
int Search(HashTable ht, int key)
{
	int hi = H(key);
	int i = hi;
	while (ht[i].key != NONE)
	{
		if (ht[i].key == key)
		{
			return i;
		}
		i = (i + 1) % m;

		if (i == hi)
		{
			break;
		}
	}
	return -1;
}

//从头到尾输出哈希表中的所有的值
void Show(HashTable ht)
{
	for (int i = 0; i < m; i++)
	{
		printf("%d ", ht[i].key);
	}
	printf("\n");
}

int main()
{
	HashTable ht;//ht指向哈希表
	InitHashTable(ht);//初始化哈希表
	int arr[16] = { 3,5,7,1,2,9,28,25,6,11,10,15,17,23,34,19 };

	//测试插入后得到的哈希表
	for (int i = 0; i < sizeof(arr)/sizeof(arr[0]); i++)
	{
		Insert(ht, arr[i]);
	}
	Show(ht);//输出哈希表

	//测试查找
	int key = 2;
	int index = Search(ht, key);
	if (index != -1)
	{
		printf("关键字%d找到了!\n",key);
	}
	else
	{
		printf("关键字%d没有找到!\n",key);
	}

	return 0;
}

  • 16
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值