[C++] 哈希的模拟实现---闭散列法(中)

本文详细介绍了闭散列法,即开放定址法,用于解决哈希冲突。通过线性探测和二次探测法寻找下一个空位置,并展示了如何使用C++实现哈希表的基本框架、插入、查找和删除操作。哈希函数根据键值转化为整数,确保模运算的有效性。当负载因子超过0.5时,哈希表会进行扩容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

定义

  • 闭散列法,又称开放定址法,当发生哈希冲突时,如果哈希表未被装满,说明在哈希表中必然还有空位置,那么可以把key存放到冲突位置中的“下一个”空位置中去。

如何寻找下一个空位置

  • 线性探测法:从发生冲突的位置开始,依次向后探测,直到寻找到下一个空位置为止;
    缺点:一旦发生哈希冲突,所有的冲突连在一起,容易产生数据“堆积”,导致搜索效率降低;
  • 二次探测法:按2次方去找“下一个”空位置。

基于闭散列法实现哈希

1)实现基本框架

hashDate

	//标识当前存储位置的状态情况
	enum Status{
		EMPTY,
		EXITS,
		DELETE
	};

	template <class K, class V>
	struct HashData{
		pair<K, V> _kv;
		Status _status = EMPTY;
	};

hashTable

  • 对于自定义类型,其构造、拷贝构造、赋值重载、析构等默认成员函数,编译器会自动生成
  • 哈希表里的数据类型为hashData
	template <class K, class V, class HashFunc>
	class HashTable{
	private:
		vector<HashData<K, V>> _table;  //vector中的数据类型为HashData
		size_t _n;  //哈希表中有效数据个数
	};

hashFunc

  • hashFunc仿函数:实现key值转化为int型,保证在哈希函数运算时能进行取模运算
	struct intHashFunc{
		int operator()(int i){
			return i;
		}
	};

	struct stringHashFunc{
		int operator()(string s){
			int count = 0;
			for (auto &e : s){
				count += e;
			}
			return count;
		}
	};

2)实现基本操作

insert插入操作

  • 判断是否需要插入-----是否需要增容(负载因子>0.5)-----线性探测法找待插入位置-----插入元素
bool insert(const pair<K, V>& kv){
			//考虑是否需要增容的问题
			if (_table.size() == 0){
				_table.resize(8);
			}
			
			HashFunc hf;
			HashData<K, V>* ret = find(kv.first);
			if (ret != nullptr){  //元素已经在哈希表中存在,不需要再次插入
				return true;
			}

			//负载因子大于0.5就增容
			if ((double)_n / (double)_table.size() > 0.5){
				HashTable<K, V, HashFunc> newhash;
				newhash._table.resize(_table.size() * 2);
				for (auto& e : _table){
					if (e._status == EXITS)
						newhash.insert(e._kv);  //把数据插入到新的哈希表中
				}
				_table.swap(newhash._table);  //交换两个哈希表的table
			}

			//插入数据
			size_t start = hf(kv.first) % _table.size();
			size_t index = start;
			size_t i = 1;
			while (_table[index]._status == EXITS){
				index = start + i;  //线性探测法
				index %= _table.size();
				++i;
			}
			_table[index]._kv = kv;
			_table[index]._status = EXITS;
			_n++;
			return true;
		}

find查找操作

HashData<K, V>* find(const K& key){
			HashFunc hf;
			size_t start = hf(key) % _table.size();
			size_t index = start;
			size_t i = 1;
			while (_table[index]._status != EMPTY){  
				if (_table[index]._status == EXITS && _table[index]._kv.first == key){
					return &_table[index];
				}
				 //往后探测下一个位置
				index = start + i;
				index %= _table.size();
				++i;
			}
			return nullptr;
		}

erase删除操作

  • 查找待删除元素的位置-----该元素的状态置为DELETE即可
bool erase(const K& key){
			HashData<K, V>* ret = find(key);
			if (ret){
				ret->_status = DELETE;
				return true;
			}
			else
				return false;
		}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值