以下代码已在gitee上开源,仓库地址:https://gitee.com/tgwTTT/c-lreant/tree/master/Hashbucket
哈希桶的实现请参考博主的上一篇文章:http://www.tgwttt.xyz/?p=157
unordered——map/set是c++11新推出的stl容器,底层采用hash表实现,访问时时间复杂度为O(1),最坏情况为O(n),这是及其极端情况和hash冲突没有处理好的情况下,下面是具体实现:
迭代器的定义:
template
struct HTIterator
{
typedef HashNode
typedef HashTable
typedef HTIterator
Node* _node;
const HT* _ht;
};
首先是其迭代器的定义,迭代器函数泛型一个定义了6的个参数
分别是:K:关键字
T:数据类型
ref:数据引用
ptr:数据指针
KeyOft:比较大小仿函数
Hash:转整形仿函数
下面是Node节点类型
HT:哈希表
下面就是迭代器operator++的实现
实现思路:iterator 中有一个指向结点的指针,如果当前桶下面还有结点,则结点的指针指向下一个结点即可。
如果当前桶走完了,则需要想办法计算找到下一个桶。
这里的难点反而是结构设计的问题。参考上面的源码,我们可以看到 iterator 中除了有结点的指针,还有哈希表对象的指针,这样当前桶走完了,要计算下一个桶就相对容易多了:
用 key 值计算出当前桶位置,依次往后找下一个不为空的桶即可。这也是我定义_ht的用意
Self& operator++()
{
if (_node->_next)
{
// 当前桶还有数据,走到当前桶下一个节点
_node = _node->_next;
}
else
{
// 当前桶走完了,找下一个不为空的桶
KeyOfT kot;
Hash hash;
size_t hashi = hash(kot(_node->_data)) % _ht->_tables.size();
++hashi;
while (hashi < _ht->_tables.size())
{
_node = _ht->_tables[hashi];
if (_node)
break;
else
++hashi;
}
// 所有桶都走完了,end()给的空标识的_node
if (hashi == _ht->_tables.size())
{
_node = nullptr;
}
}
return *this;
}
};
再下面就是 map、set的定义,因为定义比较简单,就不一一解释了
map:
#pragma once
#include"hashbucket.h"
namespace bit
{
template>
class unordered_map {
struct MapKeyOfT {
const K& operator()(const pair&kv ) {
return kv.first;
}
};
public:
bool insert(const pair&kv) {
return _ht.Insert(kv);
}
private:
hash_bucket::HashTable, MapKeyOfT,Hash>_ht;
};
}
set:
#pragma once
#include"hashbucket.h"
namespace bit
{
template>
class unordered_set {
struct SetKeyOfT {
const K& operator()(const K& key) {
return key;
}
};
public:
private:
hash_bucket::HashTable_ht;
};
}
再就是hash桶里面对iterator的定义
Iterator Begin()
{
if (_n == 0)
return End();
for (size_t i = 0; i < _tables.size(); i++)
{
Node* cur = _tables[i];
if (cur)
{
return Iterator(cur, this);
}
}
return End();
}
Iterator End()
{
return Iterator(nullptr, this);
}
ConstIterator Begin() const
{
if (_n == 0)
return End();
for (size_t i = 0; i < _tables.size(); i++)
{
Node* cur = _tables[i];
if (cur)
{
return ConstIterator(cur, this);
}
}
return End();
}
ConstIterator End() const
{
return ConstIterator(nullptr, this);
}
具体代码请参考代码仓库里面的代码
今天的文章就更新到这里了,如有不对,欢迎评论区指出,谢谢!!!
评论
我偶尔阅读 旅行者网站。酷学习旅行小技巧。 離群荒野 衷心感谢 灵感。十分 激励人。