哈希桶

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了哈希桶相关的知识,希望对你有一定的参考价值。

哈希桶:建一个存放指针的数组,将hash出的key跟数组的下标进行对应,将对应的数据链接到该位置。


eg:要存11 22 24 34 54 36 

利用模除算出位置:

11%10=1

21%10=1

24%10=4

34%10=4

54%10=4

36%10=6

技术分享

代码实现:
#define  _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
#include<string>
#include<vector>


template<class K,class V>
struct KeyValue
{
K _key;
V _value;
KeyValue<K, V>* _next;
KeyValue(const K& key, const V& value)
:_key(key),
_value(value),
_next(NULL)
{}
};


template<class K>
struct HashFuncDefault
{
size_t operator()(const K& key)
{
return key;
}
};


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<>
struct HashFuncDefault<string>
{
size_t operator()(const string& key)
{
return BKDRHash(key.c_str());
}
};


template<class K, class V, class HF = HashFuncDefault<K>>
class HashBucket
{
typedef KeyValue<K, V> KV;
public:
HashBucket()
:_size(0)
{}


bool Insert(const K& key, const V& value)
{
_CheckCapacity();
size_t index = HashFunc(key, _table.size());
KV* cur = _table[index];
while (cur)
{
if (cur->_key != key)
{
cur = cur->_next;
}
else
{
return false;
}
}
KeyValue<K, V>* tem = new KeyValue<K, V>(key, value);   //用头插法插入节点
tem->_next = _table[index];
_table[index] = tem;
_size++;
return true;
}


size_t HashFunc(const K& key, size_t capacity)
{
HF hashFunc;
 return hashFunc(key) % capacity;
}


KV* Find(const K& key)
{
size_t index = HashFunc(key, _table.size());
KV* cur = _table[index];
while (cur)
{
if (cur->_key == key)
{
return cur;
}
cur = cur->_next;
}
return NULL;
}
void Print()
{
size_t size = _table.size();
for (size_t i = 0; i < size; i++)
{
if (_table[i])
{
KV* cur = _table[i];
while (cur)
{
cout << "key:" << cur->_key << " value:" << cur->_value << " -> ";
cur = cur->_next;
}
cout << "NULL";
cout << endl;
}
}
}


void Remove(const K& key)
{
size_t index = HashFunc(key, _table.size());
KV* cur = _table[index];
if (cur == NULL)
{
return;
}
if (cur->_key == key)
{
_table[index] = cur->_next;
}
KV* prev = cur;
while (cur->_next)
{
cur = cur->_next;
if (cur->_key == key)
{
prev->_next = cur->_next;
delete cur;
cur = NULL;
_size--;
return;
}
prev = cur;
}
}
~HashBucket()
{
size_t size = _table.size();
for (size_t i = 0; i < size; i++)
{
if (_table[i])
{
KV* cur = _table[i];
while (cur)
{
KV* del = cur;
cur = cur->_next;
delete del;
}
}
}
}
protected:

void _CheckCapacity()
{
size_t newCapacity = 0;
if (_table.size() == _size)
{
newCapacity = _GetSize(_size);
vector<KV*> tmp;
tmp.resize(newCapacity);
for (size_t i = 0; i < _size; i++)
{
KV* cur = _table[i];
while (cur)
{
KeyValue<K, V>* move = cur;
cur = cur->_next;
size_t index = HashFunc(move->_key, tmp.size());
move->_next = tmp[index];            //用头插法更方便
tmp[index] = move;
}
}
_table.swap(tmp);
}
}



size_t _GetSize(const size_t size)
{
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
};
size_t i = 0;
for (; i < _PrimeSize; i++)
{
if (_PrimeList[i] <= size && i != _PrimeSize - 1)
{
i++;
}
else
{
break;
}
}
return _PrimeList[i];
}


private:
vector<KV*> _table;
size_t _size;
};



void test()
{
//HashBucket<string, string> hs;
//hs.Insert("hello", "你好");
//hs.Insert("world", "世界");
HashBucket<int, int> s;
s.Insert(1, 2);
s.Insert(2, 2);
s.Insert(54, 1);
s.Insert(53, 44);
//s.Remove(1);
//s.Remove(53);
s.Print();
}


int main()
{
test();
return 0;
}



本文出自 “fun” 博客,请务必保留此出处http://10725723.blog.51cto.com/10715723/1774036

以上是关于哈希桶的主要内容,如果未能解决你的问题,请参考以下文章

数据结构哈希表--线性探测和哈希桶及unordered_set,unordered_map代码示范

.net Dictionary 使用多少个哈希桶?

哈希表哈希桶的实现

哈希桶

哈希桶

在哈希表的上下文中,“桶条目”是啥意思?