以下代码已在gitee上开源,仓库地址:https://gitee.com/tgwTTT/c-lreant/tree/master/hash
哈希表是c++学习中重要的一部分,如c++里面的unordered_set/map都是用hash封装的,查找效率较由红黑树封装的map/set更加高效,下面是我将带领大家用开放定址法建立hash表

下面使用线性探测法建立hash表的过程
首先什么是线性探测法?

将上面的数据映射到M=11的表中,我们首先需要将数据取模

然后依次填入表中,但是数据有相同的,这就意味着发生了线性冲突,需要使用线性探测法,向后加,指导找到空位

变成了这个样子,当插入30遇到已经被19占了的情况,向后移动。但是值得我们注意的是 当负载因子(元素个数/元素空间)>0.7,我们必须对容量进行扩容。下面是实现过程
#pragma once
#include
#include
#include
using namespace std;
enum State {
EXIST,
EMPTY,
DELETE
};
template
struct HashData {
pair_kv;
State _state = EMPTY;
};
template
class HashTable {
private:
vector> _tables;
size_t _n;//数据个数
public:
HashTable()
:_tables(11)
,_n(0){ }
bool Insert(const pair& kv) {
if (Find(kv.first)) {
return false;
}
//扩容,保证负载因子在0.7左右
if (_n / _tables.size() >= 0.7) {
//vector> newtables(_tables.size()*2);
//for (auto& data : _tables) {
// i = 1;
// //旧表数据映射到新表
// while (data._state == EXIST) {
// size_t hash0 = data.first % newtables.size();
// ++i;
// }
//}
//_tables.swap(newtables);
HashTablenewht;
newht._tables.resize(_tables.size() * 2);
for (auto data : _tables) {
if(data._state==EXIST)
newht.Insert(data._kv);
}
_tables.swap(newht._tables);
}
size_t hash0 = kv.first % _tables.size();
size_t hashi = hash0;
size_t i = 1;
while (_tables[hashi]._state ==EXIST) {
//线性探测
hashi = (hashi + i)% _tables.size();
++i;
}
_tables[hashi]._kv = kv;
_tables[hashi]._state = EXIST;
++_n;
return true;
}
HashData* Find(const K& key) {
size_t hash0 = key % _tables.size();
size_t hashi = hash0;
size_t i = 1;
while (_tables[hashi]._state != EMPTY ) {
//线性探测
if (_tables[hashi]._kv.first == key && _tables[hashi]._state == EXIST) {
return &_tables[hashi];
}
hashi = (hashi + i) % _tables.size();
++i;
}
return nullptr;
}
bool Erase(const K& key) {
HashData* ret = Find(key);
if (ret == nullptr) {
cout << "删除失败" << endl;
return false;
}
else {
ret->_state = DELETE;
return true;
}
}
};
下面是测试代码:
test.cpp
#include
#include"hashT.h"
using namespace std;
void test_hash_1() {
int a[] = { 19,30,52,63,11,22 };
HashTableht;
for (auto e : a) {
ht.Insert({ e,e });
}
ht.Erase(30);
if (ht.Find(30)) {
cout << "找到了" << endl;
}
else {
cout << "没找到" << endl;
}
}
void main() {
test_hash_1();
}
测试结果:

今天的更新就到这了,如有错误,请评论区留言
评论
还没有任何评论,你来说两句吧!