构造哈希表之开链法(哈希桶)

上一篇博客中介绍了用闭散列法的二次探测和开链法构造哈希表的原理即实现方式。

构造哈希表的闭散列法之二次探测地址:http://blog.csdn.net/xyzbaihaiping/article/details/51607770

这里简单描述一下哈希桶的基本原理:

哈希表中保存包含每个key值的节点,每个节点有一个_next的指针,指向产生哈希冲突的key的节点

#pragma once
#include<iostream>
#include<vector>
#include<string>
using namespace std;

template<class K>
struct _HashFunc
{
	size_t operator()(const K& key,size_t capacity)
	{
		return key%capacity;
	}
};
template<>
struct _HashFunc<string>//string类特化
{

	static size_t _BKDRHash(const char * str)
	{
		unsigned int seed = 131; // 31 131 1313 13131 131313
		unsigned int hash = 0;
		while (*str)
		{
			hash = hash * seed + (*str++);
		}
		return (hash & 0x7FFFFFFF);
	}
	size_t operator()(const string& key, size_t capacity)
	{
		return _BKDRHash(key.c_str()) % capacity;
	}
};

template<class K,class V>
struct HashTableNode
{
	HashTableNode(const K& key, const V& value)
	:_key(key)
	, _value(value)
	,_next(NULL)
	{}
	K _key;
	V _value;
	HashTableNode<K,V>* _next;
};

const int _PrimeSize = 28;
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
};//素数表,将哈希表容量控制为素数,使用素数做除数可以减少哈希冲突
template<class K, class V, class HashFunc = _HashFunc<K> >
class HashTable
{
public:

	typedef HashTableNode<K, V> Node;

	HashTable(const HashTable<K,V>& ht)
		:_size(0)
	{
		_tables.resize(ht._tables.size());
		for (size_t i = 0; i < ht._tables.size(); i++)
		{
			Node* cur = ht._tables[i];
			while (cur)
			{
				Insert(cur->_key, cur->_value);
				cur = cur->_next;
				_size++;
			}
		}

	}
	HashTable& operator=(HashTable<K, V> ht)
	{
		swap(_tables, ht._tables);
		return *this;
	}
	~HashTable()
	{
		for (size_t i = 0; i < _tables.size(); i++)
		{
			Node* cur = _tables[i];
			while (cur)
			{
				Node* del = cur;
				cur = cur->_next;
				delete del;
			}
		}

	}
	HashTable(const size_t& capacity)
		:_size(0)
	{
		_tables.resize(_GetCapacity(0));
	}
	bool Insert(const K& key,const V& value)
	{
		_CheckCapacity();
		size_t index = HashFunc()(key,_tables.size());
		Node* cur = _tables[index];
		while (cur)
		{
			if (cur->_key == key)
				return false;
			cur = cur->_next;
		}
		Node* NewNode = new Node(key, value);
		NewNode->_next = _tables[index];
		_tables[index] = NewNode;
		_size++;
	}
	Node* Find(const K& key)
	{
		size_t index = HashFunc()(key, _tables.size());
		Node* cur = _tables[index];
		while (cur)
		{
			if (cur->_key == key)
				return cur;
			cur = cur->_next;
		}
		return NULL;
	}
	bool Remove(const K& key)
	{
		size_t index = HashFunc()(key, _tables.size());
		Node* cur = _tables[index];
		if (cur == NULL)
			return false;
		if (cur->_key == key && cur)
		{
			_tables[index] = cur->_next;
			delete cur;
			cur = NULL;
			return true;
		}
		Node* prev = NULL;
		while (cur)
		{
			prev = cur;
			cur = cur->_next;
			if (cur->_key == key)
			{
				prev->_next = cur->_next;
				delete cur;
				return true;
			}
		
		}
		return false;
	}

	void Print()
	{
		for (size_t i = 0; i < _tables.size(); i++)
		{
			Node* cur = _tables[i];
			while (cur)
			{
				cout << cur->_key << ":" << cur->_value << "->";
				cur = cur->_next;
			}
			cout << "NULL" << endl;
		}
	}
private:
	void _CheckCapacity()
	{
		if (_size == _tables.size())
		{
			size_t capacity = _GetCapacity(_size);
			vector<Node*> tab;
			tab.resize(capacity);
			for (size_t i = 0; i < _tables.size(); i++)
			{
				Node* cur = _tables[i];
				while (cur)
				{
					Node* tmp = cur;
					cur = cur->_next;
					size_t index = HashFunc()(tmp->_key, tab.size());
					tmp->_next = tab[index];
					tab[index] = tmp;
				}
				_tables[i] = NULL;
			}
			_tables.swap(tab);
		}
		
	}

	size_t _GetCapacity(const size_t& capacity)
	{
		for (size_t i = 0; i<_PrimeSize; i++)
		{
			if (capacity < _PrimeList[i])
				return _PrimeList[i];
		}
	}

private:
	vector<Node*> _tables;
	size_t _size;
};
#include"HashTableBucket.h"
void TestInt()
{
	HashTable<int, int> tab(10);
	tab.Insert(51,51);
	tab.Insert(105,105);
	tab.Insert(52,52);
	tab.Insert(3,3);
	tab.Insert(55,55);
	tab.Insert(2,2);
	tab.Insert(106,106);
	tab.Insert(53,53);
	tab.Insert(0,0);
	/*for (int i = 0; i < 53; i++)
	{
		tab.Insert(i,i);
	}
	tab.Insert(54,54);*/
	tab.Print();
	//HashTable<int, int> ht(tab);
	HashTable<int, int> ht(tab);
	ht = tab;
    /*HashTableNode<int,int>* node=tab.Find(54);
	cout << node->_key << " " << node->_value << endl;*/
	cout << ":------------" << endl;
	/*tab.Remove(0);
	tab.Print();*/
	ht.Print();
	
}
void TestString()
{
	HashTable<string, string> ht(0);
	ht.Insert("hhh","jjjj");
	ht.Insert("het", "haxi");
	ht.Insert("kk", "kkkk");
	HashTableNode<string, string>* node=ht.Find("het");
	ht.Print();
	cout << node->_key<< node->_value << endl;
}
int main()
{
	//TestInt();
	TestString();
	getchar();
	return 0;
}




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值