哈希表的讲解:
https://blog.csdn.net/lz201788/article/details/79735508
以下是哈希表的另外的实现方式:
【1.】(不使用vector)
【HashTable2.h】
#pragma once
#include<iostream>
#include<string>
using namespace std;
#define CAPACITY 11
enum Status
{
EXIST,
DELETE,
EMPTY
};
template<class K,class V>
struct HashNode
{
HashNode(K key=K(),V value=V())
:_key(key)
, _value(value)
, _status(EMPTY)
{}
K _key;
V _value;
Status _status;
};
//定义仿函数
template<class K>
struct _HashFunc
{
size_t operator()(const K& key)
{
return key;
}
};
//特化string的版本
template<>
struct _HashFunc<string>
{
static size_t BKDHash(const char* str)
{
size_t seed = 131; //13 131 1313 13131
size_t hash = 0;
while (*str)
{
hash = hash*seed + (*str);
str++;
}
return (hash & 0x7fffffff);
}
size_t operator()(const string&key)
{
return BKDHash(key.c_str()); //c_str() 返回的是一个const char* 类型的字符串
}
};
//素数表,表内为哈希表的容量,素数降低哈希冲突
const int _PrimeSize = 28;
static const unsigned long _PrimeList[_PrimeSize] =
{
53ul, 97ul, 193ul, 389ul, 769ul, 1543ul, 3079ul, 6151ul,
12289ul, 24593ul, 49157ul, 98317ul, 196613ul, 393241ul,
786433ul, 1572869ul, 3145739ul, 6291469ul, 12582917ul,
25165843ul, 50331653ul, 100663319ul, 201326611ul,
402653189ul, 805306457ul, 1610612741ul, 3221225473ul,
4294967291ul
};
template<class K,class V,class HashFunc=_HashFunc<K>>
class HashTable
{
typedef HashNode<K, V> Node;
public:
HashTable(const size_t& capacity=11)
:_size(0)
, _capacity(capacity)
{
head = new Node[capacity];
}
bool Insert(const K& key,const V& value)
{
//检查是否需要扩容
CheckCapacity();
//对key值进行取余判断插入位置
size_t index = HashTableFunc(key);
//如果存在则循环着继续找
//LineCheck(index); //(1)线性探测
SecondCheck(index); //(2)二次探测
head[index]._key = key;
head[index]._value = value;
head[index]._status = EXIST;
_size++;
return true;
}
int Find(const K& key) //查找元素
{
//先求哈希值
int index=HashTableFunc(key);
int count = _capacity;
while (count--)
{
if (head[index]._key == key)
return index;
index++;
if (index == _capacity)
index = 0;
}
return -1; //没找到
}
bool Delete(const K& key)
{
int index = Find(key);
if (index >= 0)
{
head[index]._status = DELETE;
return true;
}
return false;
}
size_t Size()const
{
return _size;
}
bool Empty()const
{
return _size == 0;
}
~HashTable()
{
if (head != NULL)
delete[]head;
_size = 0;
_capacity = 0;
}
void Display()
{
for (size_t i = 0; i < _capacity; i++)
{
cout <<i<<":"<< head[i]._key << "-->" << head[i]._value << endl;
}
}
private:
int HashTableFunc(const K& key)
{
HashFunc hf; //定义一个_HashFunc<K> 的对象hf
size_t hash = hf(key); //用hf调用相应的仿函数,返回一个整型
return (hash%_capacity); //算出哈希值并返回
}
void LineCheck(size_t& index) //线性探测
{
while (head[index]._status != EMPTY)
{
index++;
if (index == _capacity)
index = 0;
}
}
void SecondCheck(size_t& index) //二次探测
{
int num = 0;
int ret = index;
while (head[index]._status != EMPTY)
{
num++;
index = ret+ num*num;
}
}
void CheckCapacity() //扩容函数
{
//如果超过比例系数就需要扩容
if ((_size * 10) / _capacity >= 7)
{
int index = 0;
while (index<_PrimeSize)
{
if (_PrimeList[index] < _capacity)
index++;
else
{
HashTable<K, V> newHash(_PrimeList[index]);
for (size_t i = 0; i < _capacity; i++)
{
if (head[i]._status==EXIST)
newHash.Insert(head[i]._key, head[i]._value);
}
Swap(newHash);
break;
}
}
}
}
void Swap(HashTable<K, V>& newHash)
{
swap(head,newHash.head);
swap(_size,newHash._size);
swap(_capacity, newHash._capacity);
}
private:
Node* head;
size_t _size;
size_t _capacity;
};
void test3() //测试整型
{
int arr[] = {12,3,24,14,25,10,19,78,30,35};
int size = sizeof(arr) / sizeof(arr[0]);
HashTable<int, int> h1;
for (int i = 0; i < size; i++)
{
h1.Insert(arr[i], arr[i] + 3);
}
h1.Display();
}
void charTest() //测试字符型
{
HashTable<string, string> h2;
h2.Insert("1111","1111");
h2.Insert("1112", "1112");
h2.Insert("1113", "1113");
h2.Insert("1114", "1114");
h2.Insert("1115", "1115");
h2.Display();
}
【test.cpp】
#include"HashTable2.h"
int main()
{
//test();
//test2();
//test3();
charTest();
system("pause");
return 0;
}
【2.】哈希表(开散列)加迭代器
【HashIterator.h】
#pragma once
#include<iostream>
#include<vector>
#include<string>
#include<windows.h>
using namespace std;
//定义仿函数
template<class K>
struct _HashFunc
{
size_t operator()(const K& key)
{
return key;
}
};
//特化string版本
template<>
struct _HashFunc<string>
{
static size_t BDKHash(const char* str)
{
size_t seed = 131; //13 131 1313 13131 .....
size_t hash = 0;
while (*str)
{
hash = hash*seed + (*str);
str++;
}
return (hash & 0x7fffffff);
}
size_t operator()(const string& key)
{
return BDKHash(key.c_str()); //返回一个const char* 类型的字符串
}
};
template<class K,class V>
struct HashNode
{
HashNode(const K& key=K(),const V& value=V())
:Next(NULL)
, _key(key)
, _value(value)
{ }
struct HashNode* Next;
K _key;
V _value;
};
//素数表,表内为哈希表的容量,素数降低哈希冲突
const int _PrimeSize = 28;
static const unsigned long _PrimeList[_PrimeSize] =
{
53ul, 97ul, 193ul, 389ul, 769ul, 1543ul, 3079ul, 6151ul,
12289ul, 24593ul, 49157ul, 98317ul, 196613ul, 393241ul,
786433ul, 1572869ul, 3145739ul, 6291469ul, 12582917ul,
25165843ul, 50331653ul, 100663319ul, 201326611ul,
402653189ul, 805306457ul, 1610612741ul, 3221225473ul,
4294967291ul
};
template<class K, class V, class HashFunc = _HashFunc<K>>
class HashTable;
//迭代器
template<class K, class V>
struct HashIterator
{
typedef HashIterator<K, V> Iter;
typedef HashNode<K, V>* pNode;
typedef HashTable<K, V> HashTable;
HashIterator()
:_pHead(NULL)
, _ht(NULL)
{}
HashIterator(pNode _Node, HashTable* ht)
:_pHead(_Node)
, _ht(ht)
{ }
Iter& operator++()
{
_pHead = _Next(_pHead);
return (*this);
}
Iter operator++(int)
{
Iter ret(*this);
++(*this);
return ret;
}
K operator*()
{
return _pHead->_key;
}
pNode operator->()
{
return _pHead;
}
bool operator!=(Iter& s)
{
return _pHead != s._pHead;
}
bool operator==(Iter& s)
{
return _pHead == s._pHead;
}
private:
pNode _Next(pNode& _node)
{
pNode temp = _node->Next;
if (temp)
{
return temp;
}
else
{
int index = _ht->HashTableFunc(_pHead->_key)+1;
for (size_t i = index; i < _ht->Capacity(); i++)
{
pNode ret = _ht->_hash[i];
if (ret)
{
return ret;
}
}
return NULL;
}
}
private:
pNode _pHead;
HashTable* _ht;
};
template<class K,class V,class HashFunc>
class HashTable
{
typedef HashNode<K, V> Node;
friend struct HashIterator<K, V>;
typedef HashIterator<K, V> Iterator;
public:
HashTable(const size_t& capacity=11)
{
_size = 0;
_hash.resize(capacity);
}
//key可重复插入
bool InsertEqual(const K& key,const V& value)
{
//检测是否需要扩容
CheckCapacity();
//求哈希值
size_t index = HashTableFunc(key);
if (_hash[index] == NULL)
{
_hash[index] = new Node(key, value);
_size++;
return true;
}
Node*ret = _hash[index];
Node*cur = NULL;
while (ret)
{
cur = ret;
ret = ret->Next;
}
Node* newNode = new Node(key, value);
cur->Next = newNode;
_size++;
return true;
}
//key不能重复的插入
bool InsertUnique(const K& key,const V& value)
{
//检测是否需要扩容
CheckCapacity();
//求哈希值
size_t index = HashTableFunc(key);
if (_hash[index] == NULL)
{
_hash[index] = new Node(key, value);
_size++;
return true;
}
Node*ret = _hash[index];
Node*cur = NULL;
while (ret)
{
cur = ret;
if (ret->_key == key)
return false;
ret = ret->Next;
}
Node* newNode = new Node(key, value);
cur->Next = newNode;
_size++;
return true;
}
//删除有重复元素
bool DeleteEqual(const K& key)
{
size_t index = HashTableFunc(key);
Node* ret = _hash[index];
if (ret == NULL)
return false;
Node* cur = NULL;
while (ret)
{
if (ret->_key == key)
{
if (ret == _hash[index])
{
_hash[index] = ret->Next;
delete ret;
_size--;
ret = _hash[index];
}
else
{
cur->Next = ret->Next;
delete ret;
_size--;
ret = cur->Next;
}
}
else
{
cur = ret;
ret = ret->Next;
}
}
return true;
}
//删除无重复元素
bool DeleteUnique(const K& key)
{
size_t index = HashTableFunc(key);
Node* ret = _hash[index];
Node* cur = NULL;
while (ret)
{
if (ret->_key == key)
{
if (ret == _hash[index])
{
_hash[index] = ret->Next;
delete ret;
}
else
{
cur->Next = ret->Next;
delete ret;
}
_size--;
ret = NULL;
return true;
}
cur = ret;
ret = ret->Next;
}
return false;
}
//迭代器
Iterator Begin() //返回第一个元素所在的位置
{
for (size_t i = 0; i < _hash.size(); i++)
{
if (_hash[i])
{
return Iterator(_hash[i],this);
}
}
return Iterator(NULL, NULL);
}
Iterator End()
{
return Iterator(NULL,NULL);
}
bool Empty()
{
return (_size==0)
}
size_t Size()
{
return _size;
}
size_t Capacity()
{
return _hash.size();
}
size_t HashTableFunc(const K& key) //求哈希值
{
HashFunc ht; //定义一个_HashFunc<K>变量
size_t hash = ht(key);
return (hash%_hash.size());
}
void Display() //打印函数
{
Iterator it = Begin();
while (it != End())
{
//Sleep(1000);
cout <<it->_key <<"-->"<<it->_value<<endl;
it++;
}
}
~HashTable()
{
Clear();
}
private:
void Clear() //清除函数
{
size_t count = _hash.size();
for (size_t i = 0; i < count; i++)
{
if (_hash[i])
{
Node* ret = _hash[i];
Node* cur = NULL;
while (ret)
{
_hash[i] = ret->Next;
delete ret;
ret = _hash[i];
}
}
}
_size = 0;
}
void CheckCapacity() //扩容
{
if (_hash.size() == _size)
{
int newSize = 0;
int index = 0;
while (index < _PrimeSize)
{
if (_hash.size() < _PrimeList[index])
{
newSize = index;
HashTable<K, V> newHash(newSize);
size_t count = 0;
while (count < _hash.size())
{
Node* ret = _hash[count];
while (ret)
{
newHash.InsertEqual(ret->_key, ret->_value);
ret = ret->Next;
}
count++;
}
Swap(newHash);
}
index++;
}
}
}
void Swap(HashTable<K,V>& newHash) //交换地址
{
swap(_hash,newHash._hash);
swap(_size,newHash._size);
}
private:
vector<Node*> _hash;
size_t _size;
};
////////////////////////////////////测试函数
void test4()
{
int arr[] = {2,13,12,34,56,23,45};
int size = sizeof(arr) / sizeof(arr[0]);
HashTable<int, int> h1;
for (int i = 0; i < size; i++)
{
h1.InsertUnique(arr[i],arr[i]+3);
}
h1.Display();
}
void testchar4() //key值插入不能重复
{
HashTable<string, string> h2;
h2.InsertUnique("abc", "abc");
h2.InsertUnique("sed", "sed");
h2.InsertUnique("hello", "hello");
h2.InsertUnique("1111","1111");
h2.InsertUnique("1112","2222");
h2.InsertUnique("1113","3333");
/*h2.DeleteUnique("1111");
h2.DeleteUnique("hello");*/
h2.Display();
}
void Equaltest()
{
HashTable<string, string> h3;
h3.InsertEqual("1111","1111");
h3.InsertEqual("2222", "2222");
h3.InsertEqual("1111", "3333");
h3.InsertEqual("abc", "bsahd");
h3.InsertEqual("abc", "5555");
h3.DeleteEqual("abc");
h3.DeleteEqual("1111");
}
【test.cpp】
#include"HashIterator.h"
int main()
{
//test();
//test2();
//test3();
//charTest();
//test4();
testchar4();
//Equaltest();
system("pause");
return 0;
}
运行结果