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
结果截屏: