哈希表在插入和查找拥有好高的效率,当数据足够的多时,相比于平衡树,效率几乎是平衡树的两倍。
开散列哈希具有的优势就是,哈希表中存放着链表的地址,每个进来的数据通过哈希函数求得位置,存放在相应位置的链表中。查找数据时,只需要查找该数据通过哈希函数求得的位置下的链表中是否存在,就能高效的完成查找;插入时,只需要对该数据通过哈希函数求得位置的链表进行头插就可以。
#include<iostream>
#include<vector>
#include<assert.h>
using namespace std;
template<class ValueType>
struct Hashnode
{
Hashnode(const ValueType& v)
:_value(v)
, _next(NULL)
{}
Hashnode<ValueType>* _next;
ValueType _value;
};
template<class K>
struct _KofK
{
K operator()(K key)
{
return key;
}
};
template<class K, class V>
struct _KofKV
{
K operator()(const pair<K, V>& value)
{
return value.first;
}
};
template<class K>
struct _Hashfun
{
K operator()(const K& key)
{
return key;
}
};
template<class K, class ValueType, class KofValueType, template<class> class __HashFun>
class Hashtable;
template<class K, class ValueType, class Ref, class Ptr, class KofValueType, template<class> class __HashFun>
struct HashtableIterator
{
typedef Hashtable<K, ValueType, KofValueType, __HashFun> hashtable;
typedef HashtableIterator<K, ValueType, Ref, Ptr, KofValueType, __HashFun> Self;
typedef Hashnode<ValueType> node;
HashtableIterator(node* ptr = NULL, hashtable* ht = NULL)
:_ptr(ptr)
, _ht(ht)
{}
Ptr operator->()
{
return &(_ptr->_value);
}
Ref operator*()
{
return _ptr->_value;
}
Self& operator++()
{
Increase();
return *this;
}
Self operator++(int)
{
Self tmp(*this);
Increase();
return tmp;
}
Self& operator--()
{
Decrease();
return *this;
}
Self operator--(int)
{
Self tmp(*this);
Decrease();
return tmp;
}
bool operator!= (const Self& it)
{
return !operator==(it);
}
bool operator== (const Self& it)
{
return it._ptr == _ptr;
}
hashtable* _ht;
node* _ptr;
private:
void Increase()
{
assert(_ptr);
if (_ptr->_next)
{
_ptr = _ptr->_next;
return;
}
else
{
size_t index = _ht->Hashfun(_ptr->_value, _ht->_table.size()) + 1;
for (index; index<_ht->_table.size(); index++)
{
if (_ht->_table[index])
{
_ptr = _ht->_table[index];
return;
}
}
_ptr = NULL;
}
}
void Decrease()
{
size_t index = _ht->Hashfun(_ptr->_value, _ht->_table.size());
if (_ptr != _ht->_table[index])
{
node* tmp = _ht->_table[index];
while (tmp->_next != _ptr)
{
tmp = tmp->_next;
}
_ptr = tmp;
}
else
{
if (index == 0)
{
_ptr = NULL;
return;
}
else
{
node* tmp = _ht->_table[index - 1];
while (tmp->_next != NULL)
{
tmp = tmp->_next;
}
_ptr = tmp;
}
}
}
};
template<class K, class ValueType, class KofValueType, template<class> class __HashFun = _Hashfun >
class Hashtable
{
typedef Hashnode<ValueType> node;
typedef Hashtable<K, ValueType, KofValueType, __HashFun> hashtable;
friend struct HashtableIterator<K, ValueType, ValueType&, ValueType*, KofValueType, __HashFun>;
public:
typedef HashtableIterator<K, ValueType, ValueType&, ValueType*, KofValueType, __HashFun> Iterator;
public:
Hashtable()
:_size(0)
{}
Hashtable(const hashtable& h)
:_size(0)
{
for (size_t index = 0; index<h._table.size(); index++)
{
node* tmp = h._table[index];
while (tmp)
{
node* next = tmp->_next;
Insert(tmp->_value);
tmp = next;
}
}
}
hashtable& operator=(hashtable h)
{
swap(_size, h._size);
_table.swap(h._table);
return *this;
}
~Hashtable()
{
for (size_t index = 0; index<_table.size(); index++)
{
if (_table[index])
{
node* del = _table[index];
node* next = del->_next;
delete del;
del = next;
}
_table[index] = NULL;
}
}
pair<Iterator, bool> Insert(const ValueType& v)
{
CheckLoadFactory();
size_t index = Hashfun(v, _table.size());
node* tmp = new node(v);
tmp->_next = _table[index];
_table[index] = tmp;
_size++;
return make_pair(Iterator(tmp, this), true);
}
bool Erase(Iterator& it)
{
assert(it);
return Erase(*it);
}
bool Erase(ValueType& v)
{
size_t index = Hashfun(v, _table.size());
node* del = _table[index];
node* pre = del;
if (del->_value == v)
{
_table[index] = del->_next;
}
while (del != NULL)
{
if (del->_value == v)
{
pre->_next = del->_next;
delete del;
return true;
}
pre = del;
del = del->_next;
}
return false;
}
Iterator Find(const ValueType& v)
{
size_t index = Hashfun(v, _table.size());
node* tmp = _table[index];
while (tmp)
{
if (tmp->_value == v)
{
break;
}
tmp = tmp->_next;
}
return Iterator(tmp, this);
}
void CheckLoadFactory()
{
if (_size == 0 || _size * 10 / _table.size()>10)
{
_size == 0 ? _table.resize(7) : Reallocate();
}
}
void Reallocate()
{
vector<node*> newtable;
newtable.resize(GetNextPrime(_table.size()));
size_t newindex = 0;
for (size_t index = 0; index<_table.size(); index++)
{
if (_table[index])
{
node* tmp = _table[index];
_table[index] = NULL;
while (tmp)
{
node* next = tmp->_next;
newindex = Hashfun(tmp->_value, newtable.size());
tmp->_next = newtable[newindex];
newtable[newindex] = tmp;
tmp = next;
}
}
}
_table.swap(newtable);
}
size_t GetNextPrime(size_t pre)
{
const size_t _PrimeSize = 28;
static 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 index = 0; index<_PrimeSize; index++)
{
if (pre<_PrimeList[index])
return _PrimeList[index];
}
return _PrimeList[_PrimeSize - 1];
}
size_t Hashfun(const ValueType& v, size_t size)
{
KofValueType _KofValueType;
__HashFun<K> hashfun;
return (hashfun(_KofValueType(v))) % size;
}
Iterator Begin()
{
for (size_t index = 0; index<_table.size(); index++)
{
if (_table[index])
{
return Iterator(_table[index], this);
}
}
return Iterator(NULL, this);
}
Iterator End()
{
return Iterator(NULL, this);
}
private:
vector<node*> _table;
size_t _size;
};
int main()
{
Hashtable<int, int, _KofK<int> > h1;
h1.Insert(1);
h1.Insert(2);
h1.Insert(3);
h1.Insert(4);
h1.Insert(5);
h1.Insert(6);
h1.Insert(7);
h1.Insert(8);
h1.Insert(9);
h1.Insert(0);
Hashtable<int, int, _KofK<int> > h4;
h4 = h1;
Hashtable<int, int, _KofK<int> >::Iterator it = h1.Begin();
while (it != h1.End())
{
cout << *it << " ";
++it;
}
cout << endl;
Hashtable<int, int, _KofK<int> >::Iterator it4 = h4.Begin();
cout << *it4++ << endl;
it4 = h4.Begin();
cout << *++it4 << endl;
it4++;
cout << *it4 << endl;
it4++;
cout << *it4 << endl;
it4++;
cout << *it4 << endl;
it4++;
cout << *it4 << endl;
cout << *--it4 << endl;
Hashtable<int, pair<int, int>, _KofKV<int, int> > h2;
h2.Insert(pair<int, int>(1, 1));
h2.Insert(pair<int, int>(2, 1));
h2.Insert(pair<int, int>(3, 1));
h2.Insert(pair<int, int>(4, 1));
h2.Insert(pair<int, int>(5, 1));
h2.Insert(pair<int, int>(6, 1));
h2.Insert(pair<int, int>(7, 1));
h2.Insert(pair<int, int>(8, 1));
h2.Insert(pair<int, int>(9, 1));
h2.Insert(pair<int, int>(10, 1));
Hashtable<int, pair<int, int>, _KofKV<int, int>>::Iterator it2 = h2.Begin();
it2->second = 20;
Hashtable<int, pair<int, int>, _KofKV<int, int> > h3(h2);
return 0;
}