散列(哈希)表的C++简单操作和实现(线性探查)

散列(哈希)表的简述:

散列是数据结构字典的另一种表示方法,它用一个散列函数把关键字映射到散列表的具体位置。

散列表是一种面向查找的数据结构,它回避了关键词之间不断比较的麻烦,直接一步到位找到关键词的位置,是高效的。


散列函数:

散列函数可以有很多种,常见的有

(1)平方区中法:把关键词平方后,取中间三位数字,适用于位数较小的关键词。

(2)求模取余法:用一个求模函数,取得余数,被除数一般小于等于元素数量的大小。

(3)分析抽取法:把一个关键词的部分数字抽取出来作为关键词,适用于有一些规律且较大的关键词。

这其中最常用的就是求模取余法,它能比较均匀的把关键词插入散列表中。

//定义散列函数
int Hash(int key)
{
	return key%m;          //函数为f(k) = k%m;    这里m取元素数量12
}


散列表冲突时的处理

当关键词k1和关键词k2,同时进行散列函数取值后,f(k1)=f(k2),这时,散列表就发生了冲突,冲突并不可怕,但冲突造成的溢出可怕,此时就要进行冲突的处理,常见的处理方法有下面几种:

(1)线性探查法:既然当前位置被占了,就继续找后面存着的空位,进行线性的查找,不浪费剩余的空间。

(2)链地址法:让冲突发生,直接在一个位置存储多个元素,此时就可以用到单链表,在一个节点储存一个单链表,单链表来存储多个元素,当然这样也会在遍历单链表时造成更多的性能损耗。

(3)公共溢出区法:再创建一个备用的散列表,如果溢出就按顺序存储到备用表,查找时如果没在主表找到,则在备用表进行线性查找,适用于溢出较少的情况。


散列表的初始化:

#define SUCCESS 1
#define UNSUCCESS 0
#define HASHSIZE 12         //散列表长为数组长
#define NULLKEY -32768      //空值
typedef int Status;
typedef struct HashTable
{
	int *elem;         //元素存在在动态数组
	int count;           //当前元素个数
};
int m = 0;        //散列表表长 全局变量

//初始化散列表
Status InitHashTable(HashTable *h)
{
	int i;
	m = HASHSIZE;          //散列表表长设为12
	h->count = m;             //元素个数
	h->elem = new int[m];      //创建一个大小为HASHSIZE的int类型数组
	for (int i = 0; i < m; i++)
	{
		h->elem[i] = NULLKEY;    //将数组内元素设为空值
	}
	return SUCCESS;
}

散列表的插入:

这里使用的冲突处理方法为线性探查法:

//插入元素到散列表 按散列地址
void InsertHash(HashTable *h,int key)
{
	int addr = Hash(key);    //用散列函数计算关键词
	while (h->elem[addr] != NULLKEY)      //当指定元素不为空值时,发生冲突
	{
		addr = (addr + 1) % m;     //关键词线性查找散列表后面空位
	}
	h->elem[addr] = key;       //散列表指定位置为空,插入值
}
有了插入方法,就可以构造一个哈希表。

散列表的查找:

查找方法和插入方法非常类似,反向操作。

//查找散列表关键字
Status SearchHash(HashTable h, int key, int *addr)
{
	*addr = Hash(key);      //散列地址
	while(h.elem[*addr] != key)      //如果不为关键字则该地址冲突
	{
		*addr = (*addr + 1)&m;    //线性查找下面的地址
		if (h.elem[*addr] == NULLKEY || *addr ==Hash(key))
		{    //散列地址循环回到原点
			return UNSUCCESS;         //要查找的关键词不存在
		}
	}
	return SUCCESS;
}


  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值