hash_set的实现是由hash表,再加冲突处理机制实现。本文的冲突处理方法为链地址法。除了这种方法还有再hash法,开放定址法等。
对于hash的实现推荐地址:http://blog.csdn.net/eaglex/article/details/6310727
本文用的方法DJB 。
推荐参考:
http://blog.csdn.net/morewindows/article/details/7330323(此文章写的相当不错,不足:析构函数资源会泄露,
不知是否更改。浏览时需注意。)
数据结构严蔚敏版本,编程珠玑-15章字符串。
以下为代码:
#ifndef _HASH_MY_
#define _HASH_MY_
#include
using namespace std;
struct node
{
string str_val;
node *next;
};
class hash_my
{
public:
hash_my(int size = 1000);//分配资源
hash_my::~hash_my();//释放资源
unsigned int hash(string str);//hash函数
void insert(string str);//插入元素
bool find(string str);
void print();
private:
unsigned int table_size;
node **m_pnode;
};
#endif
#include "hash_my.h"
#include
hash_my::hash_my(int size )//分配资源
{
table_size = size;
m_pnode = new node *[size];
if(m_pnode == NULL)return;
memset(m_pnode,NULL,sizeof(node*)*size);//初始化
}
hash_my::~hash_my()//释放资源
{
node * p_node,*temp_node;
for (int i = 0; i < table_size;i++)
{
for (p_node = m_pnode[i];p_node != NULL;)
{
temp_node = p_node;//暂存
p_node = p_node->next;
delete temp_node;
}
}
delete []m_pnode;//最后析构
}
unsigned int hash_my::hash(string str)//hash函数
{
const int MULT = 33;
int h = 5381;//记得初始化或者0
for (int i =0 ; i < str.size();i++)
{
h = (h*MULT + str[i])%table_size;
}
return h;
}
void hash_my::insert(string str)//插入元素
{
int h = hash(str);
node * p_node;
for (p_node = m_pnode[h];p_node != NULL;p_node = p_node->next)
{
if (p_node->str_val == str)
{
return ;//已经存在,或者可在此增加计数功能
}
}
//未找到则插入
node *new_node = new node;
if(new_node == NULL)return;
new_node->str_val = str;
new_node->next = m_pnode[h];
m_pnode[h] = new_node;
}
bool hash_my::find(string str)
{
int h = hash(str);
node * p_node;
for (p_node = m_pnode[h];p_node != NULL;p_node = p_node->next)
{
if (p_node->str_val == str)
{
return true;
}
}
return false;
}
void hash_my::print()
{
node * p_node;
for (int i = 0; i < table_size;i++)
{
for (p_node = m_pnode[i];p_node != NULL;p_node = p_node->next)
{
cout<str_val<<" ";
}
}
cout<
#include "vld.h"
#include
#include
#include "hash_my.h"
#include
#include
#include
#include
using namespace std;
using namespace stdext;
const unsigned int max_num = 1000000;
int main()
{
hash_my hash_obj;
hash_set hash_cmp;
clock_t start,end;
stringstream str_sream;
string *str_store = new string[max_num];
srand((unsigned int)time(NULL));
for (int i = 0;i < max_num;i++)
{
str_sream.clear();
str_sream<>str_store[i];
str_sream.str("");//清空
//cout<
以上结果与库函数hash_set比较结果。并且进行了内存泄漏检查!
分析:1、由于类中带指针,需要对其初始化,所以需要构造函数,并且分配资源,在析构函数是否资源。
2、一个hash映射函数,外加插入函数,查找函数,以及遍历函数(用于测试用)。
遇到的问题:
1、默认形参问题,hash_my(int size = 1000);
对于这个问题,以前有接触,这次再一次体会到。首先int size = 1000带有不光是声明还有定义,
所以只能出现一次。故而在h文件或者cpp文件只能出现一次,但是当在cpp文件时,此默认形参
只能在此cpp有用,其他文件无效,故而建议在h文件使用。
2、注意指针的使用个人一开始错了俩地方
memset(m_pnode,NULL,sizeof(node*)*size);//初始化
new_node->next = m_pnode[h];
m_pnode[h] = new_node;
标注出来引以为鉴!!
3、测大量数据最好用堆(动态分配),栈的话会有限制。
string *str_store = new string[max_num];//一开始用的静态数组,直接超出范围,或不提示.
4、hash_set以前vc6.0好像在std中,现在用vs 2008的用using namespace stdext;//不然一直提示hash_set 未申明。
5、stringstream的问题,她确实给大家带来了很多方便,比如转换类型,提前字符串等,但是今天突然忘了加clear
结果一度使结果出错,而且让人摸不着头脑。在此提示各位每次使用stringstream后记得使用clear清标志,再者
如果使用了很多次,最好用stringstream.str("") 清除缓冲区的内容,否则比较耗内存(此处看网上介绍)。
hash_set 与 set比较:
hash_set内部由hash算法实现,在大容量数据面前一般查询效率高,为常量级O(1)。但是所耗内存较多!
set由rb_tree 实现,由于内部结构决定,其自带排序功能,并且稳定性好,个人猜测是标准库选择他的原因,
但是效率没有hash_set高,log(n)级别。