散列表

2021-11-15 10:13:05 浏览数 (1)

散列函数五种设计方法

1.直接地址法

2.除留余数法

3.数字分析法

4.平方取中法

5,折叠法

同理:在处理不同情况时,如果有更优解的散列函数,我们也可以自己进行设计

处理冲突的方法

1.开放定址法

(1)线性探测法

(2)二次探测法

(3) 随机探测法

总结:这上面三种方法都是在同一个数组中进行处理,没有超过数组的范畴,改变的都是d的取值方式

2. 拉链法

如何理解拉链法,下面举一个例子:

3.再散列函数法

公共溢出区法

在查找时,对给定值,通过散列函数计算得出散列地址后,先与基本表的相应位置进行比对,如果相等,则查找成功,如果不相等,则到溢出区进行顺序查找。如果相对于基本表而言,有冲突的数据很少的情况下,公共溢出区的结构对于查找性能来说还是非常高的 有冲突的关键字存储到溢出表的时候,是按照顺序存储的,而不是通过散列函数计算得出散列地址再进行存储,并且查找的时候也是按顺序查找

哈希表查找算法实现

代码语言:javascript复制
#include<iostream>
using namespace std;
//哈希表类
#define HASHSIZE 12 //默认哈希表长度为12
#define NULLKEY -32768//没插入关键字之前,默认空关键字的大小
class HashTable 
{
private:
	int* elem;//动态分配哈希表数组大小
	int count;//哈希表非空元素个数
	int len;//哈希表长度
	//散列函数----这里选择除留余数法
	int Hash(int key)
	{
		return key % len;
	}
public:
	HashTable() :len(HASHSIZE), count(0) 
	{
		elem = new int[len];//动态分配len长度大小的int数组
		//初始化哈希表数组大小
		for (int i = 0; i < len; i  )
		{
			elem[i] = NULLKEY;
		}
	}
	HashTable(int l) :len(l), count(0)
	{
		elem = new int[len];//动态分配len长度大小的int数组
	//初始化哈希表数组大小
		for (int i = 0; i < len; i  )
		{
			elem[i] = NULLKEY;
		}
	}
	//哈希表的插入
	bool insert(int key)
	{
		//先判断当前哈希表数组是否已经插满
		if (count == key)
			return false;
		//插入
		//先获取散列地址
		int addr = Hash(key);
		//如果插入的位置不为空,则发生冲突
		while (elem[addr] != NULLKEY)
		{
			//发生冲突后,这里选择开放定址法的线性探测
			addr = (addr   1) % len;
		}
		//找到空位后,插入关键字
		elem[addr] = key;
		//元素个数加一
		count  ;
		return true;
	}
	//查找关键字,查找成功返回关键字的散列地址
	int searchHash(int key)
	{
		int addr = Hash(key);//获取查找关键字的散列地址
		//如果与哈希数组中对应的散列地址存储的关键字不一样,说明需要通过线性探测法往后查找
		//这里用的线性探测法要与插入时用的方法一致
		while (elem[addr] != key)
		{
			addr = (addr   1) % len;
			//如果线性探测法,发现下一个位置为空,则表示该元素不存在,因为插入的时候用的也是线性探测法,如果插入时这个位置为空,必定会在此位置插入
			//第二个判断条件是因为从当前Hash(key)位置往右不断探测,当超过哈希数组本身长度后,会回到哈希数组起点开始遍历,一直重新再次回到Hash(key)位置时
			//表示不存在该元素-----循环回到原点
			if (elem[addr] == NULLKEY || elem[addr]==Hash(key))
			{
				return -1;//表示查不到
			}
		}
		//返回对应的散列地址
		return addr;
	}
	//释放堆区开辟的哈希数组
	~HashTable()
	{
		delete[] elem;
	}
	//获取某个散列地址对应哈希数组中的元素值
	int getKey(int addr)
	{
		return elem[addr];
	}
	//打印哈希数组
	void display()
	{
		for (int i = 0; i < len; i  )
			cout << elem[i] << " ";
		cout << endl;
	}
};
//测试-------------------------
void test()
{
	HashTable s(12);
	s.insert(12);
	s.insert(67);
	s.insert(56);
	s.insert(16);
	s.insert(25);
	s.insert(37);
	s.insert(22);
	s.insert(29);
	s.insert(15);
	s.insert(47);
	s.insert(48);
	s.insert(34);
	cout << "哈希数组打印:" << endl;
	s.display();
	cout << "查找关键字47并打印输出:" << endl;
	int addr=s.searchHash(47);
	cout << s.getKey(addr) << endl;;
}
int main()
{
	test();
	system("pause");
	return 0;
}

散列表性能分析

0 人点赞