1 原理分析
容器unordered _ map和unordered _ set的底层是HashTable,本文简单实现容器unordered_map和unordered _set的功能,将前文中的HashTable进行封装,主要改插入和查找的返回类型,使之与库里的返回类型一致。
前文:https://blog.csdn.net/qq_15000103/article/details/80270980
STL中unordered _ map和unordered _ set成员函数如下:
1.1 unordered _ set
1.2 unordered _ map
2 代码模拟实现
//HashTable.h
#pragma once
#include
#include
#include
template<class V>
struct HashNode
{
V _v;//set->k;map->kv
HashNode* _next;
HashNode(const V& v)
:_v(v)
, _next(NULL)
{}
};
template<class K>
struct Hash
{
size_t operator()(const K& key)
{
return key;
}
};
template<>
struct Hash<string>//特化,使得缺省时,若调string,则调用此函数
{
static size_t BKDRHash(const char * str)
{
unsigned int seed = 131; // 31 131 1313 13131 131313
unsigned int hash = 0;
while (*str)
{
hash = hash * seed + (*str++);
}
return (hash & 0x7FFFFFFF);
}
size_t operator()(const string& key)
{
return BKDRHash(key.c_str());
}
};
template<class K, class V, class KeyOfValue, class _HashFunc>//unordered_set->HashTable;unordered_map->HashTable>
class HashTable;
template<class K, class V, class KeyOfValue, class _HashFunc>
struct _HashTableIterator//单向迭代器
{
typedef HashNode Node;
typedef _HashTableIterator Self;
typedef HashTable HT;
Node* _node;
HashTable* _ht;
_HashTableIterator(Node* node, HT* ht)
:_node(node)
, _ht(ht)
{}
V& operator*()
{
return _node->_v;
}
V* operator->()
{
return &(operator*());
}
Self& operator++()
{
if (_node->_next)
{
_node = _node->_next;
}
else
{
KeyOfValue kov;
size_t index = _ht->HashFunc(kov(_node->_v), _ht->_table.size());
++index;
while (index < _ht->_table.size())
{
if (_ht->_table[index])
{
_node = _ht->_table[index];
break;
}
else
{
++index;
}
}
if (index == _ht->_table.size())
{
_node = NULL;
}
}
return *this;
}
Self operator++(int)
{
Self tmp(*this);
++*this;
return tmp;
}
bool operator==(const Self& s )
{
return _node == s._node;
}
bool operator!=(const Self& s)
{
return _node != s._node;
}
};
template<class K, class V,class KeyOfValue,class _HashFunc=Hash>//unordered_set->HashTable;unordered_map->HashTable>
class HashTable
{
typedef HashNode Node;
friend struct _HashTableIterator;
public:
typedef _HashTableIterator Iterator;
Iterator Begin()
{
for (size_t i = 0; i < _table.size(); i++)
{
if (_table[i])
{
return Iterator(_table[i], this);
}
}
return End();
}
Iterator End()
{
return Iterator(NULL, this);
}
HashTable()
: _size(0)
{}
std::pairbool> Insert(const V& v)
{
CheckCapacity();
KeyOfValue kov;
size_t index = HashFunc(kov(v), _table.size());
Node* cur = _table[index];
while (cur)
{
if (kov(cur->_v) == kov(v))
return make_pair(Iterator(cur,this),false);
cur = cur->_next;
}
Node* node = new Node(v);
//头插
node->_next = _table[index];
_table[index] = node;
++_size;
return make_pair(Iterator(node,this),true);
}
Iterator Find(const K& key)
{
size_t index = HashFunc(key);
Node* cur = _table[index];
KeyOfValue kov;
while (cur)
{
if (kov(cur->_v) == key)
{
return Iterator(cur,this);
}
cur = cur->_next;
}
return Iterator(NULL,this);
}
bool Remove(const K& key)
{
KeyOfValue kov;
size_t index = HashFunc(key);
Node* cur = _table[index];
if (cur == NULL)
{
return false;
}
if (kov(cur->_v) == key)//头删
{
_table[index] = cur->_next;
delete cur;
return true;
}
else//中间删
{
Node* prev = cur;
cur = cur->_next;
while (cur)
{
if (kov(cur->_v) == key)
{
prev->_next = cur->_next;
delete cur;
return true;
}
prev = cur;
cur = cur->_next;
}
}
return true;
}
size_t HashFunc(const K& key, size_t size)
{
_HashFunc hf;
return hf(key)%size;
}
size_t GetNextPrimeNum(size_t num)
{
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
};
for (size_t i = 0; i < _PrimeSize; ++i)
{
if (_PrimeList[i] > num)
{
return _PrimeList[i];
}
}
return _PrimeList[_PrimeSize - 1];
}
void CheckCapacity()
{
if (_table.size() == 0)
{
_table.resize(GetNextPrimeNum(0), NULL);
}
else if (_size == _table.size())//考虑负载因子
{
size_t newsize = GetNextPrimeNum(_table.size());
if (newsize = _table.size())
{
return;
}
vector newtable;
newtable.resize(newsize, NULL);
KeyOfValue kov;
for (size_t i = 0; i < _table.size(); ++i)
{
Node* cur = _table[i];
while (cur)
{
size_t index = HashFunc(kov(cur->_v), newsize);
Node* next = cur->_next;
//头插到newtable;
cur->_next = newtable[index];//将cur指向新表的位置
newtable[index] = cur;
cur = next;
}
_table[i] = NULL;
}
_table.swap(newtable);
}
}
private:
std::vector _table;
size_t _size;
};
//Myunorderedset.h
#pragma once
#include"HashTable.h"
template<class K,class HashFunc=Hash>
class Myunorderedset
{
struct SetKeyOfValue
{
const K&operator()(const K& key)
{
return key;
}
};
public:
typedef HASH_BUCKET::HashTable HT;
typedef typename HT::Iterator Iterator;
std::pairbool> Insert(const K& key)
{
return _ht.Insert(key);
}
Iterator Find(const K& key)
{
return _ht.Find(key);
}
Iterator Begin()
{
return _ht.Begin();
}
Iterator End()
{
return _ht.End();
}
private:
HT _ht;
};
//Myunorderedmap.h
#pragma once
template<class K, class V, class HashFunc = Hash>
class Myunorderedmap
{
struct MapKeyOfValue
{
const K&operator()(const std::pair& kv)
{
return kv.first;
}
};
public:
typedef HASH_BUCKET::HashTablestd::pair, MapKeyOfValue, HashFunc> HT;
typedef typename HT::Iterator Iterator;
std::pairbool> Insert(const std::pair& kv)
{
return _ht.Insert(kv);
}
Iterator Find(const K& key)
{
return _ht.Find(key);
}
V& operator [](const K& key)
{
std::pairbool> ret = _ht.Insert(make_pair(key,V()));
return ret.first->second;
}
Iterator Begin()
{
return _ht.Begin();
}
Iterator End()
{
return _ht.End();
}
private:
HT _ht;
};
//TestMyunorderedset.cpp
void TestMyunorderedset()
{
Myunorderedset s;
s.Insert("sort");
s.Insert("left");
s.Insert("string");
s.Insert("char");
s.Insert("char");
Myunorderedset::Iterator it = s.Begin();
while (it != s.End())
{
cout << *it << " ";
++it;
}
cout << endl;
}
//TestMyunorderedmap.cpp
void TestMyunorderedmap()
{
Myunorderedmap<string, string> dict;
dict.Insert(make_pair("string", "字符串"));
dict.Insert(make_pair("left", "左边"));
dict.Insert(make_pair("left", "剩下"));
dict["left"] = "剩余";
dict["map"] = "映射";
Myunorderedmap<string, string>::Iterator it = dict.Begin();
while (it != dict.End())
{
cout << it->first << ":" << it->second << endl;
++it;
}
}