HashTable.h
cpp
#pragma once
//顺序:
//1.哈希表
//2.封装map和set
//3.普通迭代器
//4.const迭代器
//5.insert返回值 operator[]
//6.key不能修改的问题
#include <vector>
#include <string>
namespace Hashbucket
{
template<class K>
struct DefaultHashfunc
{
size_t operator()(const K& key)
{
return (size_t)key;
}
};
template<>
struct DefaultHashfunc<string>//模板的特化
{
size_t operator()(const string& str)
{
size_t hash = 0;
for (auto ch : str)
{
hash *= 131;
hash += ch;
}
return hash;
}
};
template<class T>
struct HashNode
{
HashNode<T>* _next;
T _data;
HashNode(const T& data)
:_data(data)
, _next(nullptr)
{}
};
template<class K, class T, class KeyOfT, class HashFunc>
class HashTable;
//声明和定义一般缺省值只能给其中一个。
template<class K,class T, class Ptr, class Ref, class KeyOfT,class HashFunc>
struct HTIterator
{
typedef HashNode<T> Node;
typedef HTIterator<K, T, Ptr, Ref, KeyOfT, HashFunc> Self;
typedef HTIterator<K, T, T*, T&, KeyOfT, HashFunc> Iterator;
Node* _node;
/*HashTable<K, T, KeyOfT, HashFunc>* _pht;*/
//下面这行为什么要加const?!
const HashTable<K, T, KeyOfT, HashFunc>* _pht;
//为什么一定要传哈希表的指针?!!
HTIterator(Node* node,const HashTable<K, T, KeyOfT, HashFunc>* pht)
:_node(node)
,_pht(pht)
{ }
//==================================================
//传的是普通迭代器时,它是拷贝构造
//传的是const迭代器时,它是构造函数
HTIterator(const Iterator& it)
:_node(it._node)
,_pht(it._pht)
{ }
//==================================================
Ref operator*()
{
return _node->_data;
}
Ptr operator->()
{
return &_node->_data;
}
bool operator!=(const Self& s)
{
return _node != s._node;
}
bool operator==(const Self& s)
{
return _node == s._node;
}
Self& operator++()
{
if (_node->_next)
{
_node = _node->_next;
//当前桶还没完
}
else
{
KeyOfT kot;
HashFunc hf;
size_t hashi = hf(kot(_node->_data)) % _pht->_table.size();
++hashi;
//查找下一个不为空的桶
while (hashi < _pht->_table.size())
{
if (_pht->_table[hashi])
{
_node = _pht->_table[hashi];
return *this;
}
else
{
hashi++;
}
}
//没找到:
_node = nullptr;
}
return *this;//适用于桶还没完和没找到下一个的情况。
}
Self& operator--()
{
//???
}
};
template<class K, class T, class KeyOfT, class HashFunc = DefaultHashfunc<K>>
class HashTable
{
typedef HashNode<T> Node;
//友元声明
template<class K,class T, class Ptr, class Ref,class KeyOfT,class HashFunc>
friend struct HTIterator;
public:
typedef HTIterator<K, T, T*, T&, KeyOfT, HashFunc> iterator;
typedef HTIterator<K, T,const T*,const T&, KeyOfT, HashFunc> const_iterator;
iterator begin()
{
//找第一个桶
for (size_t i = 0; i < _table.size(); i++)
{
Node* cur = _table[i];
if (cur)
{
return iterator(cur, this);
}
}
return iterator(nullptr, this);
}
iterator end()
{
return iterator(nullptr, this);
}
const_iterator begin() const
{
//找第一个桶
for (size_t i = 0; i < _table.size(); i++)
{
Node* cur = _table[i];
if (cur)
{
return const_iterator(cur, this);
}
}
return const_iterator(nullptr, this);
}
const_iterator end() const
{
return const_iterator(nullptr, this);
}
HashTable()
{
_table.resize(10, nullptr);
}
~HashTable()
{
for (size_t i = 0; i < _table.size(); i++)
{
Node* cur = _table[i];
while (cur)
{
Node* next = cur->_next;
delete cur;
cur = next;
}
_table[i] = nullptr;
}
}
pair<iterator,bool> Insert(const T& data)
{
KeyOfT kot;
iterator it = Find(kot(data));
if (it!=end())
{
return make_pair(it,false);
}
HashFunc hf;
if (_n == _table.size())
{
size_t newSize = _table.size() * 2;
HashTable<K, T,KeyOfT,HashFunc> newHT;
newHT._table.resize(newSize, nullptr);
for (size_t i = 0; i < _table.size(); i++)
{
Node* cur = _table[i];
while (cur)
{
Node* next = cur->_next;
//头插到新表
size_t hashi = hf(kot(cur->_data)) % newHT._table.size();
cur->_next = newHT._table[hashi];
newHT._table[hashi] = cur;
cur = next;
}
_table[i] = nullptr;
}
_table.swap(newHT._table);
}
size_t hashi = hf(kot(data)) % _table.size();
//头插
Node* newnode = new Node(data);
newnode->_next = _table[hashi];
_table[hashi] = newnode;
_n++;
//return make_pair(&_table[hashi],true);
//要返回的值里有iterator类型,是HTIterator类typedef后的结果,类中
//有两个值:Node*和哈希表的指针,所以不能只返回新插入的那个节点的指针
//要构造iterator类型再返回,如下:
return make_pair(iterator(newnode, this), true);
//this为指向当前HashTable对象的指针。
}
iterator Find(const K& key)
{
HashFunc hf;
KeyOfT kot;
//形参已经是K类型了,无需取出
//size_t hashi = hf(kot(key)) % _table.size();
size_t hashi = hf(key) % _table.size();
Node* cur = _table[hashi];
while (cur)
{
if (kot(cur->_data) == key)
{
return iterator(cur,this);
}
cur = cur->_next;
}
return iterator(nullptr,this);
}
bool Erase(const K& key)
{
HashFunc hf;
KeyOfT kot;
size_t hashi = hf(key) % _table.size();
Node* prev = nullptr;
Node* cur = _table[hashi];
while (cur)
{
if (kot(cur->_data) == key)
{
if (prev == nullptr)
{
_table[hashi] = cur->_next;
}
else
{
prev->_next = cur->_next;
}
//执行到这里时说明已找到要删的值并且已删除。
_n--;
delete cur;
return true;
}
prev = cur;
cur = cur->_next;
}
return false;
}
void Print()
{
for (size_t i = 0; i < _table.size(); i++)
{
printf("[%d]->", i);
Node* cur = _table[i];
while (cur)
{
cout << cur->_data<< "->";
cur = cur->_next;
}
printf("NULL\n");
}
cout << endl;
}
private:
vector<Node*> _table;
size_t _n = 0;
};
}
UnorderedMap.h
cpp
#pragma once
#include "HashTable.h"
namespace Q
{
template<class K,class V>
class unordered_map
{
struct MapKeyOfT
{
//const K& operator()(const pair<K, V>& kv) const ai改法
//???
const K& operator()(const pair<K, V>& kv)
{
return kv.first;
}
};
public:
typedef typename Hashbucket::HashTable<K, pair<const K, V>, MapKeyOfT>::iterator iterator;
typedef typename Hashbucket::HashTable<K, pair<const K, V>, MapKeyOfT>::const_iterator const_iterator;
iterator begin()
{
return _ht.begin();
}
iterator end()
{
return _ht.end();
}
const_iterator begin() const
{
return _ht.begin();
}
const_iterator end() const
{
return _ht.end();
}
pair<iterator,bool> insert(const pair<K, V>& kv)
{
return _ht.Insert(kv);
}
V& operator[](const K& key)
{
pair<iterator, bool> ret = _ht.Insert(make_pair(key,V()));
return ret.first->second;
}
private:
Hashbucket::HashTable<K, pair<K, V>, MapKeyOfT> _ht;
};
}
UnorderedSet.h
cpp
#pragma once
#include "HashTable.h"
namespace Q
{
template<class K>
class unordered_set
{
struct SetKeyOfT
{
const K& operator()(const K& key)
{
return key;
}
};
public:
typedef typename Hashbucket::HashTable<K, K, SetKeyOfT>::const_iterator iterator;
typedef typename Hashbucket::HashTable<K, K, SetKeyOfT>::const_iterator const_iterator;
iterator begin()
{
return _ht.begin();
}
iterator end()
{
return _ht.end();
}
const_iterator begin() const
{
return _ht.begin();
}
const_iterator end() const
{
return _ht.end();
}
pair<const_iterator, bool> insert(const K& key)
{
pair<typename Hashbucket::HashTable<K, K, SetKeyOfT>::iterator, bool> ret = _ht.Insert(key);
return pair<const_iterator, bool>(ret.first, ret.second);
}
/*bool insert(const K& key)
{
return _ht.Insert(key);
}*/
private:
Hashbucket::HashTable<K, K, SetKeyOfT> _ht;
};
}
test.cpp
cpp
#include <iostream>
using namespace std;
#include "HashTable.h"
#include "UnorderedSet.h"
#include "UnorderedMap.h"
int main()
{
Q::unordered_set<int> us;
us.insert(5);
us.insert(8);
us.insert(2);
us.insert(3);
us.insert(1);
Q::unordered_set<int>::iterator it = us.begin();
while (it != us.end())
{
cout << *it << " ";
++it;
}
cout << endl;
Q::unordered_map<string, string> dict;
dict.insert(make_pair("sort", "排序"));
dict.insert(make_pair("left", "左边"));
dict.insert(make_pair("insert", "插入"));
dict.insert(make_pair("xxxx", "yyy"));
for (auto& kv : dict)
{
cout << kv.first << ":" << kv.second << endl;
}
return 0;
}