hashtable模板的簡單實現
知識標籤: hashtable, template, 函數指針, hash, C++, container, C++11
轉載註明鏈接出處
代碼中有註釋,直接上代碼:
hashtable.h如下:
#ifndef __HASHTABLE_H__
#define __HASHTABLE_H__
#include<vector>
#include<list>
template<typename T>
class hashtable
{
public:
typedef size_t (*HT)(const T&);
//構造函數,初始化list數組大小,hashtable元素個數,哈希函數
//參數numLists = 100一定要放後面,因爲它有默認值
hashtable(HT ht, size_t numLists = 100) : TLists(numLists), m_num(0), phash(ht){}
~hashtable(){}
bool isin(const T& t)
{//判斷t是否在hashtable中
std::list<T>& alist = TLists[myhash(t)];
if(alist.end() == contain(t))
return false;
else
return true;
}
//插入一個hashtable中不存在的值
bool insert_unique(T& t)
{
std::list<T>& alist = TLists[myhash(t)];
if(contain(t) != alist.end())
{
return false;
}
insert(t);
}
//插入一個hashtable中可能存在的值,不檢查唯一性
void insert(T& t)
{
//負載係數(loading factor),意指元素個數除以表格大小。此負載係數不大於1
//如果當前hashtable中元素個數大於vector的大小
if(m_num + 1 > TLists.size())
{
resize2();
}
//這句代碼不能寫在if上面
std::list<T>& alist = TLists[myhash(t)];
alist.push_back(t);
++m_num;
}
//刪除一個元素
bool remove(const T& t)
{
std::list<T>& alist = TLists[myhash(t)];
typename std::list<T>::iterator iter = contain(t);
if(iter == alist.end())
{
return false;
}
else
{
alist.erase(iter);
--m_num;
return true;
}
}
//清空hashtable
bool clear()
{
typename std::vector<std::list<T> >::iterator iter = TLists.begin();
//遍歷list數組
while(iter != TLists.end())
{
(*iter++).clear();
}
m_num = 0;
}
//依次打印hashtable所有元素
void show()
{
typename std::vector<std::list<T> >::iterator i = TLists.begin();
typename std::list<T>::iterator j;
while(i != TLists.end())
{
j = (*i).begin();
while(j != (*i).end())
{
//注:T類型必須支持operator<<
std::cout << *j++ << '\t' << std::flush;
}
std::cout << std::endl;
++i;
}
std::cout << "m_num = " << m_num << std::endl;
std::cout << "TLists.size() : " << TLists.size() << std::endl;
}
private:
//list數組, hashtable存儲結構
std::vector<std::list<T> > TLists;
size_t m_num; //hashtable中元素個數
//函數指針,類型T的hash函數
size_t (*phash)(const T&);
private:
//判斷t是否在hashtable中
typename std::list<T>::iterator contain(const T& t)
{
std::list<T>& alist = TLists[myhash(t)];
typename std::list<T>::iterator iter= alist.begin();
while(iter != alist.end())
{
//注意:類型T必須有==運算符
if(t == *iter)
{
return iter;
}
++iter;
}
return alist.end();
}
//hashtable自增長爲原先2倍大小
void resize2()
{
//備份
std::vector<std::list<T> > oldLists = TLists;
//擴容
TLists.resize(2 * TLists.size());
typename std::vector<std::list<T> >::iterator iter_new = TLists.begin();
while(iter_new != TLists.end())
{
(*iter_new++).clear();
}
m_num = 0;
//遍歷hashtable,把所有元素插入新hashtable
typename std::vector<std::list<T> >::iterator i = oldLists.begin();
typename std::list<T>::iterator j;
while(i != oldLists.end())
{
j = (*i).begin();
while(j != (*i).end())
{
insert(*j++);
}
++i;
}
}
size_t myhash(const T& t)
{//返回list數組下標
size_t val_hash = phash(t);
val_hash = val_hash % TLists.size();
return val_hash;
}
};
#endif
main.cpp文件如下:
#include<iostream>
#include<string>
#include<functional>
#include "hashtable.h"
class node
{
public:
node(std::string st, size_t sc)
{
str = st;
score = sc;
}
friend std::ostream& operator<<(std::ostream& fout, node nd);
friend bool operator==(node nd1, node nd2);
std::string str;
size_t score;
};
std::ostream& operator<<(std::ostream& out, node nd)
{
out << "( " << nd.str << ", " << nd.score << " )";
}
bool operator==(node nd1, node nd2)
{
if(nd1.str == nd2.str)
{
return true;
}
else
{
return false;
}
}
size_t myhash(const node& nd)
{
//利用string字段返回hash值
return std::hash<std::string>()(nd.str);
}
int main(void)
{
hashtable<node> ht(&myhash, 6);
node nd1("小明", 66);
node nd2("小花", 77);
node nd3("小紅", 88);
node nd4("小王", 56);
node nd5("小李", 99);
node nd6("小時", 100);
node nd7("小周", 90);
node nd8("小郭", 67);
node nd9("小吳", 87);
node nd10("小馬", 79);
node nd11("小黃", 92);
ht.insert(nd1);
ht.insert(nd2);
ht.insert(nd3);
ht.insert(nd4);
ht.insert(nd5);
ht.insert(nd6);
ht.insert(nd7);
ht.insert(nd8);
ht.insert(nd9);
ht.insert(nd10);
ht.insert(nd11);
ht.show();
std::cout << "----------------------------" << std::endl;
ht.remove(nd3);
if(ht.isin(nd3))
std::cout<< "nd3 is in hashtable !" << std::endl;
else
std::cout << "nd3 is not in hashtable !" << std::endl;
std::cout << "----------------------------" << std::endl;
ht.clear();
ht.show();
return 0;
}
編譯如下:
g++ main.cpp -o main -std=c++11
我在代碼中用到了C++11標準,所以編譯時添加-std=c++11
結果截屏: