哈希表一个简单的实现
hash table(哈希表) 哈希表最大的优点,就是把数据的存储和查找消耗的时间大大降低,几乎可以看成是常数时间;而代价仅仅是消耗比较多的内存。然而在当前可利用内存越来越多的情况下,用空间换时间的做法是值得的。另外,编码比较容易也是它的特点之一。
其基本原理是:使用一个下标范围比较大的数组来存储元素。可以设计一个函数(哈希函数,也叫做散列函数),使得每个元素的关键字都与一个函数值(即数组下标,hash值)相对应,于是用这个数组单元来存储这个元素;也可以简单的理解为,按照关键字为每一个元素“分类”,然后将这个元素存储在相应“类”所对应的地方,称为桶。
但是,不能够保证每个元素的关键字与函数值是一一对应的,因此极有可能出现对于不同的元素,却计算出了相同的函数值,这样就产生了“冲突”,换句话说,就是把不同的元素分在了相同的“类”之中。 总的来说,“直接定址”与“解决冲突”是哈希表的两大特点。
hash_map,首先分配一大片内存,形成许多桶。是利用hash函数,对key进行映射到不同区域(桶)进行保存。其插入过程是:
- 得到key
- 通过hash函数得到hash值
- 得到桶号(一般都为hash值对桶数求模)
- 存放key和value在桶内。
其取值过程是:
- 得到key
- 通过hash函数得到hash值
- 得到桶号(一般都为hash值对桶数求模)
- 比较桶的内部元素是否与key相等,若都不相等,则没有找到。
- 取出相等的记录的value。
#include <cstdlib>
#include <iostream>
#include <cassert>
#include <vector>
#include <ctime>
#include <algorithm>
using namespace std;
class HashNode
{
public:
int key;
int value;
HashNode *next;
HashNode(int k, int v):key(k), value(v), next(NULL)
{
}
};
class HashTable
{
public:
HashTable(int slot = 5);
~HashTable();
void Insert(int key, int value);
int Remove(int key);
int Query(int key, int &value);
void Print();
private:
int m_slot;
int m_length;
vector<HashNode*> m_bucket;
};
HashTable::HashTable(int slot /* = 5 */):m_slot(slot), m_length(0)
{
for (int i = 0; i < slot; i++)
{
m_bucket.push_back(0);
}
}
HashTable::~HashTable()
{
for (int i = 0; i < m_slot; i++)
{
if (m_bucket[i] != NULL)
{
HashNode *temp = m_bucket[i];
HashNode *next = NULL;
while (temp != NULL)
{
next = temp->next;
delete temp;
temp = next;
}
}
}
}
void HashTable::Insert(int key, int value)
{
int num = (unsigned int)key % m_slot;
HashNode *temp = NULL;
try
{
if (m_bucket[num] != NULL)
{
temp = m_bucket[num];
while (temp->next != NULL)
{
temp = temp->next;
}
temp->next = new HashNode(key, value);
}
else
{
m_bucket[num] = new HashNode(key, value);
}
}
catch (bad_alloc &ex)
{
cout << ex.what() << endl;
}
catch(...)
{
cout << "unkowned exception!" << endl;
}
}
int HashTable::Query(int key, int &value)
{
int num = (unsigned int)key % m_slot;
HashNode *temp = NULL;
if (m_bucket[num] != NULL)
{
temp = m_bucket[num];
while (temp != NULL)
{
if (temp->key == key)
{
value = temp->value;
return 0;
}
temp = temp->next;
}
}
return -1;
}
int HashTable::Remove(int key)
{
int num = (unsigned int)key % m_slot;
HashNode *temp = m_bucket[num];
HashNode *mPre = NULL;
if (temp != NULL)
{
while (temp != NULL)
{
if (temp->key == key)
{
if (mPre != NULL)
{
mPre->next = temp->next;
}
else
{
m_bucket[num] = temp->next;
}
delete temp;
return 0;
}
mPre = temp;
temp = temp->next;
}
}
cout << "no elements with the specified key" << endl;
return -1;
}
void HashTable::Print()
{
for (int i = 0; i < m_slot; i++)
{
cout << "bucket" << i <<endl;
HashNode *temp = m_bucket[i];
if (temp != NULL)
{
while (temp != NULL)
{
cout << " <" << temp->key << "," << temp->value << "> ";
temp = temp->next;
}
}
else
{
cout << endl;
}
cout << endl;
}
}
int main(int argc, char *argv[])
{
HashTable h(10);
int value;
srand(unsigned int(time(NULL)));
for (int i = 0; i < 24; i++)
{
int random = rand() % 100;
h.Insert(random, random + 10);
}
h.Remove(56);
h.Print();
/*
h.Query(13, value);
cout << value << endl;
*/
return 0;
}