哈希表的增删查改的效率很高,是O(1),比搜索二叉树要快很多。那么他是怎么实现的呢?他与计数排序有点相似就是通过映射的方式实现。不过在哈希表中不需要开这么的数据,它只需要开一部分空间然后使用除留余数法去实现,这个方法的缺点就是会导致哈希冲突很集中。并且哈希表是不能满的,因为哈希表要控制他的负载因子(负载因子 = 表中数据/表的大小 衡量哈希表满的程度。负载因子越大,增删查改的效率越低。一般负载因子在0.7左右开始增容。但是负载因子越小,浪费空间越多,以下是代码实现
enum State
{
EMPTY, EXITS, DELETE,
};
template<class T>
struct HashData
{
T _data;
State _state;//用于查看下一个位置是是被删除还是本来就是空的
};
template<class K, class T, class KOFV>
class HashTable
{
typedef HashData<T> HashData;
public:
bool Insert(const T& d)
{
//负载因子 = 表中数据/表的大小 衡量哈希表满的程度
//负载因子越大,增删查改的效率越低
//一般负载因子在0.7左右开始增容
//但是负载因子越小,浪费空间越多
KOFV kofv;
if (_table.size() == 0 || _num * 10 / _table.size() > 7)
{
//开新空间并且拷贝过去
//重新映射
//释放旧空间
//int newcapacity = _table.size() == 0 ? 10 : _table.size() * 2;
//vector<HashData> newtable;
//newtable.resize(newcapacity);
//for (int i = 0; i < _table.size(); i++)
//{
// int index = kofv(_table[i]._data) % newtable.size();
// if (newtable[i]._state == EXITS)
// {
// while (_table[index]._state == EXITS)
// {
// ++index;
// if (index == _table.size())
// index = 0;
// }
// }
// newtable[index]= _table[i];
//}
//_table.swap(newtable);
HashTable<K, T, KOFV> newht;
int newcapacity = _table.size() == 0 ? 10 : _table.size() * 2;
newht._table.resize(newcapacity);
for (int i = 0; i < _table.size(); i++)
{
if (_table[i]._state == EXITS)
{
newht.Insert(_table[i]._data);
}
}
_table.swap(newht._table);
}
int index = kofv(d) % _table.size();
while (_table[index]._state == EXITS)
{
if (_table[index]._data == kofv(d))
return false;
++index;
if (index == _table.size())
index = 0;
}
_table[index]._data = d;
_table[index]._state = EXITS;
++_num;
return true;
}
HashData* Find(const K& key)
{
KOFV kofv;
int index = key % _table.size();
//if (key == kofv(_table[index]._data))
//{
// if (_table[index]._stata == EXITS)
// return &_table[index];
// else//DELETE
// return nullptr;
//}
//else
//{
// ++index;
// if (_table[index]._state == EMPTY)
// {
// return nullptr;
// }
// else
// {
// {
// ++index;
// if (index == _table.size())
// index = 0;
// }
// return &_table[index];
// }
//}
while (_table[index]._state != EMPTY)
{
if (kofv(_table[index]._data) == key)
{
if (_table[index]._state == EXITS)
return &_table[index];
else
return nullptr;
}
++index;
if (index == _table.size())
index = 0;
}
return nullptr;
}
bool Erase(const K& key)
{
HashData* ret = Find(key);
if (ret)
{
ret->_state = DELETE;
--_num;
return true;
}
else
{
return false;
}
}
private:
vector<HashData> _table;
size_t _num = 0;
};
template<class K>
struct SetkeyOfv
{
const K& operator()(const K& key)
{
return key;
}
};