散列表(Hash table,也叫哈希表),是根据关键码值(Key, value)而直接进行访问的数据结构。也就是说,它通过吧关键码值映射到表中的一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。
哈希表的原理非常简单:
若关键字为K,则其值存放在f(K)的位置。由此,不需要比较便可直接取得所查记录。称这个对应关系f为散列函数,按这个思想建立的表为散列表。
除留余数法:取关键值被某个不大于散列表长m的数p除后的所得的余数为散列地址。Hash(Key)= Key%P;
但是,不管是直接定址法还是除留余数法都会产生哈希冲突,即不同的Key值经过处理得到相同的值。
#include
#include
#include
#include
using namespace std;
//线性探测法
enum STATE
{
EMPTY,
EXIST,
DELETE,
};
template
struct __HashFunc
{
size_t operator()(const K& k)
{
return k;
}
};
//特化
template<>
struct __HashFunc
{
size_t operator()(const string& k)
{
return BKDHash(k.c_str());
}
static size_t BKDHash(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);
}
};
template
struct HashNode
{
pair _kv;
STATE _s;
HashNode()
:_s(EMPTY)
{}
};
template>
class HashTable
{
typedef HashNode Node;
public:
HashTable()
:_size(0)
{}
HashTable(size_t n)
:_size(0)
{
_tables.resize(n);
}
pair Insert(const pair& kv)
{
_CheckCapacity();
size_t index = _GetIndex(kv.first);
while (_tables[index]._s == EXIST)
{
//检查是否存在
if (_tables[index]._kv.first == kv.first)
return make_pair(&_tables[index], false);
++index;
if (index == _tables.size())
index = 0;
}
_tables[index]._kv = kv;
_tables[index]._s = EXIST;
++_size;
return make_pair(&_tables[index], true);
}
Node* Find(const K& key)
{
size_t index = _GetIndex (key);
while (_tables[index]._s != EMPTY)
{
if (_tables[index]._kv.first == key)
{
if (_tables[index]._s == EXIST)
return &_tables[index];
else
return NULL;
}
++index;
if (index == _tables.size())
index = 0;
}
return NULL;
}
bool Remove(const K& key)
{
Node* del = Find(key);
if (del != NULL)
{
del->_s = DELETE;
--_size;
return true;
}
return false;
}
void Print()
{
size_t size = _tables.size();
for (size_t i = 0; i < size; ++i)
{
if (_tables[i]._s == EXIST)
{
cout << _tables[i]._kv.first << "-- "<<_tables[i]._kv.second<<" ";
}
}
cout << endl;
}
V& operator[](const K& key)
{
pair ret = Insert(make_pair(key, V()));
return ((ret.first)->_kv).second;
}
protected:
size_t _GetIndex(const K& key)
{
HashFunc k;
return k(key) % _tables.size();
}
void Swap(HashTable ht)
{
swap(_size, ht._size);
_tables.swap(ht._tables);
}
void _CheckCapacity()
{
if (_tables.size() == 0)
{
_tables.resize(53);
}
else if (_size * 10 / _tables.size() == 7)
{
size_t newSize = _GetNextprime(_tables.size());
HashTable newHT(newSize);
for (size_t i = 0; i < _tables.size(); ++i)
{
if (_tables[i]._s == EXIST)
{
newHT.Insert(_tables[i]._kv);
}
}
this->Swap(newHT);
}
}
size_t _GetNextprime(size_t n)
{
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 (n < _PrimeList[i])
return _PrimeList[i];//找到要找的下一个素数
}
assert(false);
}
protected:
vector _tables;
size_t _size;
};
void TestHash()
{
int a[] = { 89, 18, 49, 58, 9 };
HashTable ht;
for (size_t i = 0; i < sizeof(a) / sizeof(a[0]); ++i)
{
ht.Insert(make_pair(a[i], i));
}
ht.Insert(make_pair(10, 1));
ht.Insert(make_pair(11, 1));
ht.Insert(make_pair(12, 1));
ht.Insert(make_pair(13, 1));
ht.Insert(make_pair(14, 1));
ht.Print();
cout<> ht1;
ht1.Insert(make_pair("Left", "左边"));
ht1.Insert(make_pair("Left", "剩余"));
ht1.Print();
ht1["Left"] = "剩余";
ht1.Print();
}
//int main()
//{
// TestHash();
// system("pause");
// return 0;
//}
#include
#include
using namespace std;
template
struct HashNode
{
pair _kv;
HashNode* _next;
HashNode(const pair& kv)
:_kv(kv)
, _next(NULL)
{}
};
template
struct _HashFunc
{
size_t operator()(const K& key)
{
return key;
}
};
//特化
template<>
struct _HashFunc
{
size_t operator()(const string& key)
{
return BKDRHash(key.c_str());
}
protected:
//字符串哈希处理算法
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);
}
};
//声明
template
class HashTableBucket;
template
struct __HashTableIterator
{
typedef HashNode Node;
typedef __HashTableIterator< K, V, HashFunc, ValueTypePtr, ValueTypeRef> Self;
Node* _node;
HashTableBucket* _ht;
__HashTableIterator(Node* node, HashTableBucket* ht)
:_node(node)
, _ht(ht)
{}
ValueTypeRef operator*()
{
return _node->_kv;
}
ValueTypePtr operator->()
{
return &(operator*());
}
bool operator == (const Self& s)const
{
return _node == s._node;
}
bool operator !=(const Self& s)const
{
return _node != s._node;
}
Self& operator++()
{
_node = _Next(_node);
return *this;
}
protected:
Node* _Next(Node* node)
{
Node* next = node->_next;
if (next)
return next;
else
{
size_t index = _ht->_HashFunc(node->_kv.first) + 1;
for (; index < _ht->_tables.size(); ++index)
{
next = _ht->_tables[index];
if (next)
return next;
}
}
return NULL;
}
};
template>
class HashTableBucket
{
public:
typedef HashNode Node;
typedef __HashTableIterator*, pair&> Iterator;
friend Iterator;
public:
HashTableBucket()
:_size(0)
{}
HashTableBucket(const size_t n)
:_size(0)
{
_tables.resize(n);
}
~HashTableBucket()
{
_Clear();
_size = 0;
}
V& operator[](const K& key)
{
pair ret = Insert(make_pair(key, V()));
return ((ret.first)->_kv).second;
}
pair Insert(const pair& kv)
{
_Check();
size_t index = _HashFunc(kv.first);
Node* cur = _tables[index];
while (cur)
{
if (cur->_kv.first == kv.first)
{
return make_pair(cur, false);
}
cur = cur->_next;
}
//头插
Node* newNode = new Node(kv);
newNode->_next = _tables[index];
_tables[index] = newNode;
++_size;
return make_pair(_tables[index], true);
}
Node* Find(const K& key)
{
size_t index = _HashFunc(key);
Node* cur = _tables[index];
while (cur)
{
if (cur->_kv.first == key)
return cur;
cur = cur->_next;
}
return false;
}
bool Remove(const K& key)
{
size_t index = _HashFunc(key);
Node* cur = _tables[index];
Node* parent = NULL;
if (cur == NULL)
return false;
while (cur)
{
if (cur->_kv.first == key)
{
if (cur == _tables[index])
{
_tables[index] = cur->_next;
}
else
{
parent->_next = cur->_next;
}
delete cur;
cur = NULL;
--_size;
break;
}
parent = cur;
cur = cur->_next;
}
return false;
}
void Print()
{
for (size_t i = 0; i < _tables.size(); ++i)
{
Node* cur = _tables[i];
while (cur)
{
cout << cur->_kv.first << " ";
cur = cur->_next;
}
}
cout << endl;
}
Iterator Begin()
{
for (size_t i = 0; i < _tables.size(); ++i)
{
Node* cur = _tables[i];
if (cur)
return Iterator(cur, this);
}
return Iterator(NULL, this);
}
Iterator End()
{
return Iterator(NULL, this);
}
protected:
void _Check()
{
if (_tables.size() == 0 || _size / _tables.size() >= 1)
{
size_t newSize = _GetPrimenum(_tables.size());
HashTableBucket newTable(newSize);
for (size_t i = 0; i < _tables.size(); ++i)
{
Node* cur = _tables[i];
while (cur)
{
newTable.Insert(make_pair(((cur->_kv).first), ((cur->_kv).second)));
cur = cur->_next;
}
}
_Swap(newTable);
}
}
void _Swap(HashTableBucket& ht)
{
swap(_size, ht._size);
_tables.swap(ht._tables);
}
size_t _HashFunc(const K& key)
{
HashFunc hf;
return hf(key) % _tables.size();
}
size_t _GetPrimenum(const size_t& sz)
{
const int Primesize = 28;
static const unsigned long Primenum[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 (int i = 0; i < Primesize; ++i)
{
if (Primenum[i] > sz)
{
return Primenum[i];
}
}
return sz;
}
void _Clear()
{
for (size_t i = 0; i < _tables.size(); ++i)
{
Node* cur = _tables[i];
while (cur)
{
Node* del = cur;
cur = cur->_next;
delete del;
}
_tables[i] = NULL;
}
}
protected:
vector _tables;
size_t _size;
};
void TestHashTableBucket()
{
int a[] = { 89, 18, 49, 58, 9 };
HashTableBucket ht;
for (size_t i = 0; i < sizeof(a) / sizeof(a[0]); ++i)
{
ht.Insert(make_pair(a[i], 1));
}
ht.Insert(make_pair(10, 1));
ht.Insert(make_pair(53, 1));
ht.Insert(make_pair(54, 1));
ht.Insert(make_pair(55, 1));
ht.Insert(make_pair(56, 1));
ht.Insert(make_pair(106, 1));
ht.Insert(make_pair(212, 1));
ht.Print();
HashTableBucket>::Iterator it = ht.Begin();
while (it != ht.End())
{
cout << it->first << " ";
++it;
}
cout << endl;
ht.Remove(53);
ht.Remove(212);
ht.Remove(106);
ht.Remove(49);
ht.Print();
HashTableBucket> ht1;
ht1.Insert(make_pair("Left", "左边"));
ht1.Insert(make_pair("Left", "剩余"));
ht1["Left"] = "剩余";
HashTableBucket>::Iterator it1 = ht1.Begin();
while (it1 != ht1.End())
{
cout << (it1->first).c_str() << " ";
++it1;
}
cout << endl;
}
int main()
{
TestHashTableBucket();
system("pause");
return 0;
}