处理哈希冲突的开链法——哈希桶


“test.cpp”

#include<iostream>
using namespace std;
#include"HashList.h"
#include<string>
void test()
{
	HashList<string,int> hl;
	string str[] = {"hash","table","xiao","hai","xia"};
	
	size_t size = sizeof(str)/sizeof(str[0]);
	for(int i = 0;i < size;i++)
	{
		hl.Insert(str[i],i);
	}
	hl.Display();

	cout<<endl;
	hl.Remove("xiao");
	hl.Display();

}

int main()
{
	test();
	system("pause");
	return 0;
}


“HashList.h”

#pragma once
#include<vector>
#include<string>

template<class K,class V>
struct KVNode
{
	K _key;
	V _value;
	KVNode<K,V>* _next;

	KVNode(const K& key = K(),const V& value = V())
		:_key(key)
		,_value(value)
		,_next(NULL)
	{}
};

template<class K>
struct __HashFunc
{
	size_t operator()(const K& key)
	{
		return key;
	}
};

//模板的特化
template<>
struct __HashFunc<string>
{
	static size_t BKDRHash(const char* str)
	{
		unsigned int seed = 131;
		unsigned int hash = 0;
		while(*str)
		{
			hash = hash*seed + (*str++);
		}

		return (hash & 0x7FFFFFFF);
	}
	size_t operator()(const string& str)
	{
		return BKDRHash(str.c_str());
	}
};

template<class K,class V,class HashFunc = __HashFunc<K>>
class HashList
{
	typedef KVNode<K,V> Node;
public:
	HashList()
		:_size(0)
	{}

	~HashList()
	{
		for(int i = 0; i < _table.size();i++)
		{
			Node* cur = _table[i];

			while(cur)
			{
				Node* next = cur->_next;

				delete cur;

				cur = next;
			}
		}

		_size = 0;
		_table.clear();
	}
public:
	Node* Find(const K& key)
	{
		for (int i = 0;i < _table.size();i++)
		{
			Node* cur = _table[i];

			while (cur)
			{
				if (cur->_key == key)
				{
					return cur;
				}
				cur = cur->_next;
			}
		}
		return NULL;
	}
	bool Remove(const K& key)
	{
		//繁琐啰嗦的解法
		//Node* prev = NULL;
		//for (int i = 0;i < _table.size();i++)
		//{
		//	Node* cur = _table[i];

		//	while (cur)
		//	{
		//		if (cur->_key == key)
		//		{
		//			//判断删除的是否为头结点
		//			if (prev == NULL)
		//				_table[i] = cur->_next;
		//			else
		//				//删除节点不是头结点
		//				prev->_next = cur->_next;
		//			
		//			delete cur;
		//			return true;
		//		}

		//		prev = cur;
		//		cur = cur->_next;
		//	}
		//}
		//return false;

		size_t index = _HashFunc(key,_table.size());
		Node* cur = _table[index];
		Node* prev = NULL;

		while (cur)
		{
			if (cur->_key == key)
			{
				//判断删除的是否为头结点
				if (prev == NULL)
					_table[index] = cur->_next;
				else
					//删除节点不是头结点
					prev->_next = cur->_next;
					
				delete cur;
				return true;
			}

			prev = cur;
			cur = cur->_next;
		}

		return false;
	}
	bool Insert(const K& key,const V& value)
	{
		_Check();

		if (Find(key))
		{
			return false;
		}
		size_t index = _HashFunc(key,_table.size());
		Node* cur = new Node(key,value);

		//头插法
		cur->_next = _table[index];
		_table[index] = cur;

		_size++;

		return true;
	}
	void Display()
	{
		for (int i = 0;i < _table.size();i++)
		{
			Node* cur = _table[i];

			cout<<"table["<<i<<"]  = ";
			while (cur)
			{
				//cout<<"_table["<<i<<"] = "<<cur->_key<<"->";
				cout<<cur->_key<<"->";
				cur = cur->_next;
			}

			cout<<"NULL"<<endl;
		}
	}
protected:
	void _Check()
	{
		//第一次进来时,和当负载因子为1时
		if (_table.size() == 0 || _size == _table.size())
		{
			int size = _GetPrimeNum(_table.size());
			//HashList<K,V,HashFunc> tmp;
			vector<Node*> tmp;
			tmp.resize(size);

			for (int i = 0;i < _table.size();i++)
			{
				Node* cur = _table[i];

				while (cur)
				{
					//从旧表中取下节点
					Node* next = cur->_next;
					_table[i] = next;

					//取出的节点重新插入
					size_t index = _HashFunc(cur->_key,tmp.size());
					cur->_next = tmp[index];
					tmp[index] = cur;

					cur = next;
				}
			}
			tmp.swap(_table);
		}
	}

	size_t _HashFunc(const K& key,size_t size)
	{
		HashFunc hf;
		return hf(key)%size;
	}

	size_t _GetPrimeNum(int num)
	{
		// 使用素数表对齐做哈希表的容量,降低哈希冲突
		const int _PrimeSize = 28;
		static const unsigned long _PrimeList [_PrimeSize] =\
		{\
		53ul, 97ul, 193ul, 389ul, 769ul,1543ul, 3079ul, 6151ul, 12289ul, 24593ul,49157ul, 98317ul, 196613ul, 393241ul,786433ul,1572869ul, 3145739ul, 6291469ul, 12582917ul,25165843ul,50331653ul, 100663319ul, 201326611ul, 402653189ul,805306457ul,1610612741ul, 3221225473ul, 4294967291ul\
		};

		for(int i = 0;i < _PrimeSize;i++)
		{
			if(num < _PrimeList[i])
				return _PrimeList[i];
		}

		return _PrimeList[_PrimeSize - 1];
	}
private:
	vector<Node*> _table;
	size_t _size;
};


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值