1. 哈希桶概念
在C++中,哈希桶是一种用于实现哈希表的数据结构。哈希表是一种高效的数据结构,用于存储键值对,并支持快速的插入、查找和删除操作。
哈希桶的基本思想是通过将键映射到桶中的索引来存储和访问数据。具体实现中,通常使用一个数组来表示桶,每个桶可以存储一个或多个键值对。为了将键映射到桶中的索引,通常使用哈希函数来计算键的哈希值,然后对桶的数量取模,得到键的索引。
哈希桶可以理解为一个指针数组,数组的每个元素都是一个指针,而这个指针是一个单链表的表头,数组的每一个位置都挂着一个单链表。
如图所示:
2. 哈希桶的基础模型
class HashBucket
{
typedef HashBucketNode<V> Node;
typedef Node* PNode;
public:
HashBucket(size_t capacity)
: _table(GetNextPrime(capacity))
, _size(0)
{}
~HashBucket()
{
Clear();
}
private:
vector<Node*> _table;
size_t _size;
};
3. 哈希桶的插入
哈希桶的插入有以下步骤
注意:
- 这里的插入都是不插入重复元素
- 注意扩容的问题
代码如下:
Node* Insert(const V& data)
{
CheckCapacity();
size_t bucketNo = HashFunc(data);
Node* pCur = _table[bucketNo];
while (pCur)
{
if (pCur->_data == data)
return nullptr;
pCur = pCur->_pNext;
}
pCur = new Node(data);
pCur->_pNext = _table[bucketNo];
_table[bucketNo] = pCur;
++_size;
return pCur;
}
扩容的代码:
void CheckCapacity()
{
if (_size == _table.capacity())
{
for (size_t i = 0; i < _table.capacity(); ++i)
{
Node* pCur = _table[i];
while (pCur)
{
_table[i] = pCur->_pNext;
size_t bucketNo = ht.HashFunc(pCur->_data);
pCur->_pNext = ht._table[bucketNo];
ht._table[bucketNo] = pCur;
}
}
this->Swap(ht);
}
}
4. 哈希桶的删除
删除有以下步骤
- 先用哈希函数找到删除元素的位置
- 从该位置的头节点开始,遍历链表
- 找到元素,开始删除,变换节点
代码如下:
bool Erase(const V& data)
{
size_t bucketNo = HashFunc(data);
Node* pCur = _table[bucketNo];
Node* pPre = nullptr;
while (pCur)
{
if (data == pCur->_data)
{
if (_table[bucketNo] == pCur)
{
_table[bucketNo] = pCur->_pNext;
}
else
{
pPre->_pNext = pCur->_pNext;
}
delete pCur;
--_size;
return true;
}
pPre = pCur;
pCur = pCur->_pNext;
}
return false;
}
5. 哈希桶的查找
查找的步骤如下:
- 先用哈希函数确定元素的位置
- 遍历该位置的链表,找到元素
Node* Find(const V& data)
{
size_t bucketNo = HashFunc(data);
Node* pCur = _table[bucketNo];
while (pCur)
{
if (data == pCur->_data)
return pCur;
pCur = pCur->_pNext;
}
return nullptr;
}