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 
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张图片

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




你可能感兴趣的:(数据结构)