zoukankan      html  css  js  c++  java
  • 无聊写的HashTable~

    写了个HashTable的模板类, 因为C++不是很专业所以写的有点挫, 模仿SGI STL的HashTable写的。

    SGI STL用的vector, 我木有用, 主要是想锻炼下。~ 

    在数据增长到千万级的时候,内存占用居然达到了坑爹的1.2G, 我一直以为是内存泄露,结果实测以后发现确实就是要占用这么多空间~。。

    希望能找到什么优化方法。~

    模板类:

    /************************************************************************
    * @file      : HashTable.h
    * @author    : kevin <zhangtaopy-kevin@hotmail.com>
    * @date      : 2012/9/6 9:52:25
    * @brief     : 
    *
    * $Id: $
    /************************************************************************/
    #ifndef __HASHTABLE_H__
    #define __HASHTABLE_H__
    
    #include <stdlib.h>
    #include <memory.h>
    #include <Windows.h>
    
    // -------------------------------------------------------------------------
    static const int number_of_primes = 28;
    static const unsigned long prime_list[number_of_primes] = 
    {
    	53,				97,				193,			389,			769,
    	1543,			3079,			6151,			12289,			24593,
    	49157,			98317,			196613,			393241,			786433,
    	1572869,		3145739,		6291469,		12582917,		25165843,
    	50331653,		100663319,		201326611,		402653189,		805306457,
    	1610612741,		3221225473ul,	4294967291ul	
    };
    
    template <class Value>
    struct __hash_node
    {
    	__hash_node* next;
    	Value val;
    };
    
    template <class Value, class Hashfunc, class EqualKey>
    class HashTable
    {
    public:
    	typedef Hashfunc hasher;
    	typedef EqualKey key_equal;
    	typedef __hash_node<Value> node;
    
    public:
    	~HashTable();
    	HashTable(unsigned long ulSize);
    	HashTable(unsigned long ulSize, const Hashfunc& hf, const EqualKey& eq);
    	void init_bucket(unsigned long ulSize);
    	void resize(bool isUnique);
    	int	 insert_unique(const Value& obj);
    	int	 insert_equal(const Value& obj);
    	int  insert_unique_noresize(const Value& obj);
    	int	 insert_equal_noresize(const Value& obj);
    	int  find(const Value& obj);
    
    private:
    	unsigned long	m_ulFullSize;
    	unsigned long	m_ulCurSize;
    	hasher			m_hash;
    	key_equal		m_equals;
    	node**			m_bucket;
    };
    
    
    unsigned long LowerBound(const unsigned long* primelist, int n, unsigned long key)
    {
    	int start = 0;
    	int end = n-1;
    
    	if(n == 0)
    		return -1;
    
    	while(start <= end)
    	{
    		int mid = (end - start)/2 + start;
    		if(key > primelist[mid])
    		{
    			start = mid + 1;
    		}
    		else if(key < primelist[mid])
    		{
    			end = mid - 1;
    		}
    		else
    		{
    			return primelist[mid];
    		}
    	}
    	if(end != n-1)
    		return primelist[end+1];
    	else
    		return primelist[n];
    }
    
    
    template <class V, class Hf, class Eq>
    HashTable<V,Hf,Eq>::HashTable(unsigned long ulSize, const Hf& hf, const Eq& eq):m_ulCurSize(0),m_bucket(NULL),m_ulFullSize(0)
    {
    	init_bucket(ulSize);
    }
    
    template <class V, class Hf, class Eq>
    HashTable<V,Hf,Eq>::HashTable(unsigned long ulSize):m_ulCurSize(0),m_bucket(NULL),m_ulFullSize(0)
    {
    	init_bucket(ulSize);
    }
    
    template <class V, class Hf, class Eq>
    HashTable<V,Hf,Eq>::~HashTable()
    {
    	if(m_bucket != NULL)
    		free(m_bucket);
    }
    
    
    template <class V>
    __hash_node<V>* create_node(const V& obj)
    {
    		__hash_node<V>* p = new __hash_node<V>;
    		p->next = NULL;
    		p->val = obj;
    
    		return p;
    }
    
    
    template <class V>
    void destory_node(__hash_node<V>* p)
    {
    	delete p;
    }
    
    
    template <class V, class Hf, class Eq>
    void HashTable<V,Hf,Eq>::init_bucket(unsigned long ulSize)
    {
    	m_ulFullSize = LowerBound(prime_list, number_of_primes, ulSize);
    	m_bucket = (node**)malloc(sizeof(node*) * m_ulFullSize);
    	memset(m_bucket,	0,	sizeof(node*) * m_ulFullSize);
    }
    
    
    template <class V, class Hf, class Eq>
    void HashTable<V,Hf,Eq>::resize(bool isUnique)
    {
    	if(m_ulCurSize > m_ulFullSize && m_ulCurSize < prime_list[number_of_primes-1])
    	{
    		node**			oldbucket = NULL;
    		node			*p = NULL,*q = NULL;
    		unsigned long	ulSize = 0;
    
    		printf("resize() cursize:%ld , fullsize:%ld,\n", m_ulCurSize, m_ulFullSize);
    		oldbucket = m_bucket;
    		ulSize = m_ulFullSize;
    		m_ulCurSize = 0;
    		m_ulFullSize = LowerBound(prime_list, number_of_primes, m_ulFullSize + 1);
    		m_bucket = (node**)malloc(sizeof(node*) * m_ulFullSize);
    		memset(m_bucket,	0,	sizeof(node*) * m_ulFullSize);
    		//将原来的所有元素移到新的bucket中
    		for(unsigned long i=0; i< ulSize; i++)
    		{
    			if(oldbucket[i] == NULL)
    				continue;
    			q = oldbucket[i];
    			do
    			{
    				if(isUnique)
    					insert_unique_noresize(q->val);
    				else
    					insert_equal_noresize(q->val);
    				p = q;
    				q = q->next;
    				destory_node(p);
    			}while(q != NULL);
    		}
    		if(oldbucket != NULL)
    			free(oldbucket);
    	}
    }
    
    
    template <class V, class Hf, class Eq>
    int HashTable<V,Hf,Eq>::insert_unique_noresize(const V& obj)
    {
    	unsigned long key = m_hash(obj, m_ulFullSize);
    	node *p = NULL, *q = NULL;
    	bool isExist = false;
    
    	if(m_bucket[key] == NULL)
    	{
    		m_bucket[key] = create_node(obj);
    	}
    	else
    	{
    		q = m_bucket[key];
    		do
    		{
    			if(m_equals(q->val, obj))
    			{
    				//已经存在相同的节点了。
    				isExist = true;
    				break;
    			}
    			p = q;
    			q = q->next;
    		}while(q != NULL);
    
    		if(!isExist)
    		{
    			p->next = create_node(obj);
    		}
    	}
    
    	m_ulCurSize ++;
    	return 1;
    }
    
    template <class V, class Hf, class Eq>
    int HashTable<V,Hf,Eq>::insert_unique(const V& obj)
    {
    	insert_unique_noresize(obj);
    	resize(true);
    	return 1;
    }
    
    template <class V, class Hf, class Eq>
    int HashTable<V,Hf,Eq>::insert_equal_noresize(const V& obj)
    {
    	unsigned long key = m_hash(obj, m_ulFullSize);
    	node *p = NULL, *q = NULL;
    
    	p = create_node(obj);
    	if(m_bucket[key] == NULL)
    	{
    		m_bucket[key] = p;
    	}
    	else
    	{
    		p->next = m_bucket[key]->next;
    		m_bucket[key]->next = p;
    	}
    
    	m_ulCurSize ++;
    	return 1;
    }
    
    template <class V, class Hf, class Eq>
    int HashTable<V,Hf,Eq>::insert_equal(const V& obj)
    {
    	insert_equal_noresize(obj);
    	resize(false);
    	return 1;
    }
    
    template <class V, class Hf, class Eq>
    int HashTable<V,Hf,Eq>::find(const V& obj)
    {
    	unsigned long key = m_hash(obj, m_ulFullSize);
    	node *p = NULL;
    
    	if(m_bucket[key] != NULL)
    	{
    		p = m_bucket[key];
    		do
    		{
    			if(m_equals(p->val, obj))
    				return 1;
    			p = p->next;
    		}while(p != NULL);
    	}
    	else
    		return 0;
    
    	return 0;
    
    }
    
    #endif /* __HASHTABLE_H__ */
    

      

    测试代码:

    #include "stdafx.h"
    #include "HashTable.h"
    
    struct st 
    {
    	int key;
    	int value;
    };
    
    struct st_equal
    {
    	bool operator() (const st& first, const st& second) const
    	{
    		return first.value == second.value;
    	}
    };
    
    struct st_hash
    {
    	unsigned long operator() (const st& first, const unsigned long n) const
    	{
    		return first.value % n;
    	}
    };
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    	HashTable<st, st_hash, st_equal> myHashTable(10);
    	st tmp;
    	int count = 0;
    	for(unsigned long i = 0; i<4294967291; i++)
    	{
    		tmp.key = 10;
    		tmp.value = i;
    		myHashTable.insert_unique(tmp);
    	}
    	tmp.value = 10;
    	myHashTable.find(tmp);
    	tmp.value = 64;
    	myHashTable.find(tmp);
    	return 0;
    }
    

      

  • 相关阅读:
    沈询:事务与分布式事务原理与实现
    c++ 幕客网
    Meet Dgraph — an open source, scalable, distributed, highly available and fast graph databas
    开发与系统管理----开发工具 左蓝
    奇虎360技术博客
    java 相关软件使用趋势
    长亭技术专栏 安全攻防技术分享
    tcp/ip RFC
    gentoo and arclinux
    孙鑫视频VC++深入详解学习笔记
  • 原文地址:https://www.cnblogs.com/whoiskevin/p/2674254.html
Copyright © 2011-2022 走看看