hash_set实现

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 <string>
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 <iostream>

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<<p_node->str_val<<"  ";
		}

	}
	cout<<endl;
}

#include "vld.h"
#include <iostream>
#include <hash_set>
#include "hash_my.h"
#include <string>
#include <cstdlib>
#include <ctime>
#include <sstream>


using namespace std;
using namespace stdext;

const unsigned int max_num = 1000000;
int main()
{
	hash_my hash_obj;
	hash_set<string> 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<<rand();//int范围内
		str_sream>>str_store[i];
		str_sream.str("");//清空
		//cout<<str_store[i]<<" ";
		
	}
 
	start = clock();
	
	for (int j = 0;j < max_num;j++)
	{
		hash_obj.insert(str_store[j]);
	 
	}
	
	for (int k = 0;k < max_num;k++)
	hash_obj.find(str_store[k]);
 
	end = clock();

	cout<<"hash_my 用时:"<<end-start<<endl;
	
	start = clock();

	for (int j = 0;j < max_num;j++)
	   hash_cmp.insert(str_store[j]);

	for (int k = 0;k < max_num;k++)
		hash_cmp.find(str_store[k]);

	end = clock();
	cout<<"hash_set 用时:"<<end-start<<endl;

	//hash_obj.print();
	delete []str_store;
	return 1;
}

sy_njust_ecjtu

以上结果与库函数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)级别。




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值