【C++】闭散列实现哈希表

哈希概念:

  • 顺序结构以及平衡树中,查找一个元素需要时间复杂度为O( l o g 2 N log2N log2N),搜索效率较低
  • 理想搜索状态:不经过任何比较,通过某种函数使元素的存储位置和它的关键码之间建立一 一映射的关系,则查找通过该函数很快可以找到元素位置
  • 哈希表是一种以空间换时间的思想

闭散列(开放定址法):

  • 底层使用数组存储元素
  • 映射关系:通过对元素 关键字(key) 取模数组容量,计算哈希地址
  • 哈希冲突:映射到的位置有不同 key 值元素
    • 线性探测:每次向后偏移一个位置,直到找到一个空位置,进行插入
      • 缺点:如果出现冲突次数较多,则冲突的元素都会向后偏移,则造成数据的堆积
    • 二次探测: 为了避免数据堆积,找下一个元素位置方法: p o s = p o s + i 2 pos = pos + i^2 pos=pos+i2

哈希节点:

enum state
{
	EMPTY,
	EXIST,
	DELETE
};
template <class K, class V>
struct HashNode
{
	pair<K, V> _value;
	state _state;
	
	HashNode(const pair<K, V>& value = pair<K, V>())
		:_value(value)
		, _state(EMPTY)
	{}
};
  • 哈希函数:除留余数法:key % _table.size()
  • 解决哈希冲突:线性探测
    • 通过哈希函数找到哈希地址,如果发生了哈希冲突,则向后偏移到第一个空位置
  • 扩容时机:负载因子 > 0.7 的时候,将容量增至 2 倍,并将原始数据插入到新哈希中
    • 负载因子: 哈希表中存在的值 / 哈希表的容量
  • 扩容方法
    • 将数组容量增至2倍,并将原始哈希表中的元素插入新的哈希表
  • 删除一个元素:
    • 将元素的属性设置为 delete,并将size- -
    • 原因:在哈希表中寻找一个键值对是通过该位置状态向后偏移的,如果遇到EMPTY还没有直到,则返回 nullptr ,因此删除一个元素时不能直接将状态设置为EMPTY

哈希表的操作:

template <class K, class V>
class HashTable
{
public:
	HashTable(size_t n = 10)
	{
		// 这里必须使用resize!
		_table.resize(n);
		_size = 0;
	}
	bool Insert(const pair<K, V>& value)
	{
		// 1.先检查容量
		checkCapacity();
		// 2.通过哈希函数计算位置
		int index = value.first % _table.size();
		// 3.找第一个空位置
		while (_table[index]._state == EXIST)
		{
			// 当前key值已存在
			if (_table[index]._value.first == value.first)
				return false;
			index = (index + 1) % _table.size();
		}
		_table[index]._value = value;
		_table[index]._state = EXIST;
		++_size;
		return true;
	}
	void checkCapacity()
	{
		// 1.计算负载因子
		if (_size * 10 / _table.size() >= 7)
		{
			HashTable ht(2 * _table.size());

			// 将旧表中元素插入新表
			for (int i = 0; i < _table.size(); ++i)
			{
				if (_table[i]._state == EXIST)
					ht.Insert(_table[i]._value);
			}
			swap(_table, ht._table);
		}
	}
	HashNode<K, V>* find(const K& key)
	{
		int index = key % _table.size();
		while (_table[index]._state == !EMPTY)
		{
			if (_table[index]._state == EXIST && _table[index]._value.first == key)
				return &_table[index];
			index = (index + 1) % _table.size();
		}
		return nullptr;
	}
	bool erase(const K& key)
	{
		HashNode<K, V>* ptr = find(key);
		if (ptr)
		{
			ptr->_state = DELETE;
			--_size;
			return true;
		}
		return false;
	}
private:
	vector<HashNode<K, V>> _table;
	size_t _size;
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值