</pre><pre name="code" class="cpp">#pragma once
#include <iostream>
#include <string>
using namespace std;
template <class K,class V>
//节点的结构
struct HashTableNode
{
K _key;//关键字
V _value;//关键字对应的值
};
//状态
enum Status
{
EMPTY, //空
DELETE, //删除
EXITS //正常存在
};
//仿函数
template <typename K>
struct _HashFunc
{
size_t operator()(const K& key)
{
return key;
}
};
template<>
struct _HashFunc<string>
{
size_t operator()(const string & key)
{
size_t ikey = 0;
char * str = (char *)key.c_str();
while (*str)
{
ikey += *str;
*str++;
}
return ikey;
}
};
//哈希表的二次探测
template <typename K,typename V>
class HashTable
{
//重命名为Node
typedef HashTableNode<K, V> Node;
public:
//构造
HashTable(size_t capacity = 10)
:_size(0)
,_capacity(capacity)
,_tables(new Node[capacity])
,_status(new Status[capacity])
{
//_status初始化为空
for (size_t i = 0; i < _capacity; i++)
{
_status[i] = EMPTY;
}
}
//析构函数
~HashTable()
{
if (_tables)
{
delete[]_tables;
}
if (_status)
{
delete[]_status;
}
}
public:
//插入
bool Insert(const K& key, const V& value)
{
//是否需要扩容
_CheckCapacity();
//哈希地址
size_t index = HashFunc(key);
size_t start = index;
//二次检测
size_t i = 1;
//如果该地址处存在数据
while (_status[index] == EXITS)
{
//该数据已经存在
if (_tables[index]._key == key)
{
return false;
}
//二次探测
index = start + i*i;
index %= _capacity;
i++;
}
_tables[index]._key = key;
_tables[index]._value = value;
_status[index] = EXITS;
_size++;
return true;
}
//删除
bool Remove(const K& key)
{
//哈希地址
size_t index = HashFunc(key);
size_t start = index;
size_t i = 1;
while (_status[index] == EXITS)
{
//该数据存在
if (_tables[index]._key == key)
{
_status[index] = DELETE;
return true;
}
//数据不再当前位置
index = start + i*i;
index %= _capacity;
i++;
if (index == start)
{
return false;
}
}
return false;
}
//查找
Node * Find(const K & key)
{
size_t index = HashFunc(key);
size_t start = index;
size_t i = 1;
while (_status[index] == EXITS)
{
//该数据存在
if (_tables[index]._key == key)
{
return &_tables[index];
}
//数据不再当前位置
index = start + i*i;
index %= _capacity;
i++;
if (index == start)
{
return NULL;
}
}
return NULL;
}
//打印
void Print()
{
cout << "0表示(空);1表示(删除);2表示(正常)" << endl;
for (size_t i = 0; i < _capacity; i++)
{
cout << "{" << _status[i] << "," << _tables[i]._key << ","
<< _tables[i]._value << "}" << "->";
}
cout << endl;
}
protected:
//是否扩容
void _CheckCapacity()
{
//载荷因子大于等于0.7时扩容
if (_size * 10 % _capacity >= 7)
{
HashTable<K, V> tmp(2 * _capacity);//新的容积
for (size_t i = 0; i < _capacity; i++)
{
//如果数据正常
if (_status[i] == EXITS)
{
//插入到新的哈希表中
tmp.Insert(_tables[i]._key, _tables[i]._value);
}
}
Swap(tmp);
}
}
//交换
void Swap(HashTable<K, V> & tmp)
{
swap(_tables, tmp._tables);
swap(_status, tmp._status);
swap(_size, tmp._size);
swap(_capacity, tmp._capacity);
}
//计算哈希地址(除留取余法)
size_t HashFunc(const K & key)
{
_HashFunc<K> hf;
return hf(key) % _capacity;
}
private:
Node * _tables;//哈希表
Status* _status;//状态
size_t _size;//存储数据的大小
size_t _capacity;//容量
};
哈希表(散列表)
哈希表,根据关键字(key)直接访问在内存存储位置的数据结构。
它通过一个关键值的函数将所需的数据映射到表中的位置来访问数据,这个映射函数叫做散列函数,存放记录的数组叫做散列表。
构造哈希表的几种方法
直接定址法--取关键字的某个线性函数为散列地址,Hash(Key)= Key 或 Hash(Key)= A*Key + B,A、B为常数。
除留余数法--取关键值被某个不大于散列表长m的数p除后的所得的余数为散列地址。Hash(Key)= Key % P。
哈希冲突/哈希碰撞不同的Key值经过哈希函数Hash(Key)处理以后可能产生相同的值哈希地址,我们称这种情况为哈希冲突。任意的散列函数都不能避免产生冲突。
散列表的载荷因子=填入表中的元素个数/散列表的长度
源代码实现如下:
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.