1. 程式人生 > >構造雜湊表之二次探測法

構造雜湊表之二次探測法

<pre name="code" class="cpp">//HashTable.h
#pragma once
#include<iostream>
#include <string>
using namespace std;
enum State
{
	EMPTY,//空
	EXITS,//存在
	DELETE//已刪除
};

template<class K, class V>
struct HashTableNode
{
	K _key;
	V _value;
};




template<class K>
struct _HashFunc
{
	size_t operator()(const K& key,const size_t& capacity)//雜湊函式,仿函式
	{
		return key / capacity;
	}

};
template<>
struct _HashFunc<string>//模板特化
{
private:
	unsigned int _BKDRHash(const char *str)//key為字串時雜湊函式
	{
		unsigned int seed = 131; // 31 131 1313 13131 131313 etc..
		unsigned int hash = 0;

		while (*str)
		{
			hash = hash * seed + (*str++);
		}
		return (hash & 0x7FFFFFFF);
	}
public:
	size_t operator()(const string& key,const size_t& capacity)//仿函式
	{

		return _BKDRHash(key.c_str()) % capacity;
	}

};
template<class K, class V,class HashFunc=_HashFunc<K>>
class HashTable
{

	typedef HashTableNode<K, V> Node;
public:
	HashTable(size_t capacity = 10)
		:_tables(new Node[capacity])
		, _states(new State[capacity])
		, _size(0)
		, _capacity(capacity)
	{}
	~HashTable()
	{
		if (_tables != NULL)
		{
			delete[] _tables;
			delete[] _states;
		}
	
	}
	HashTable(const HashTable<K, V>& ht)
	{
		HashTable<K, V> tmp(ht._capacity);
		for (size_t i = 0; i < ht._capacity; i++)
		{
			tmp.Insert(ht._tables[i]._key, ht._tables[i]._value);
		}
		this->Swap(tmp);
	}
	HashTable& operator=(HashTable<K, V> ht)
	{
		this->Swap();
		return *this;
	}
	bool Insert(const K& key, const V& value)
	{
		_CheckCapacity();
		size_t index = HashFunc()(key, _capacity);
		size_t i = 1;
		while (_states[index] == EXITS)//二次探測
		{
			if (_tables[index]._key == key)
			{
				return false;
			}
			index = index + 2 * i - 1;
			index %= _capacity;
			++i;
		}
		_tables[index]._key = key;
		_tables[index]._value = value;
		_states[index] = EXITS;
		++_size;
		return true;
	}

	bool Find(const K& key)
	{
		size_t index = HashFunc()(key, _capacity);
		size_t start = index;
		size_t i = 1;
		while (_states[index] != EMPTY)//根據二次探測法查詢
		{
			if (_tables[index]._key == key)
			{
				if (_states[index] != DELETE)
					return true;
				else
					return false;
			}
			index = index + 2 * i - 1;
			index %= _capacity;
			if (start == index)
				return false;
		}
		return false;
	}
	bool Remove(const K& key)
	{
		size_t index = HashFunc()(key, _capacity);
		size_t start = index;
		size_t i = 1;
		while (_states[index] != EMPTY)//根據二次探測法刪除
		{
			if (_tables[index]._key == key)
			{
				if (_states[index] != DELETE)
				{
					_states[index] = DELETE;
					_size--;
					return true;
				}
				else
					return false;
			}
			index = index + 2 * i - 1;
			index %= _capacity;
			if (start == index)
				return false;
		}
		return false;


	}
	void Print()
	{
		for (size_t i = 0; i < _capacity; i++)
		{
			//printf("%d-[%s:%s] \n", _states[i], _tables[i]._key, _tables[i]._value);
			cout << _states[i] << " " << _tables[i]._key << " " << _tables[i]._value<<endl;
		}
	}
private:
	void Swap(HashTable<K, V>& tmp)
	{
		swap(_tables, tmp._tables);
		swap(_states, tmp._states);
		swap(_size, tmp._size);
		swap(_capacity, tmp._capacity);
	}
	void _CheckCapacity()//增容
	{
		if (_size * 10 / _capacity == 6)
		{
			HashTable<K, V> tmp(_capacity * 2);
			for (size_t i = 0; i < _capacity; i++)
			{
				if (_states[i] == EXITS)
					tmp.Insert(_tables[i]._key, _tables[i]._value);
			}
			this->Swap(tmp);
		}
	}

private:
	Node* _tables;//雜湊表
	State* _states;//狀態表
	size_t _size;
	size_t _capacity;
};


</pre><pre code_snippet_id="1711228" snippet_file_name="blog_20160608_3_3809584" name="code" class="cpp">//test.cpp
#include<iostream>
#include "HashTable.h"
void testInt()
{
	HashTable<int, int> table(10);
	table.Insert(89, 89);
	table.Insert(18, 18);
	table.Insert(49, 49);
	table.Insert(58, 58);
	table.Insert(9, 9);
	//table.Insert(45, 45);
	//table.Insert(2, 2);
	table.Print();
	HashTable<int, int> table1(table);
	table1.Print();
	bool ret = table.Find(9);
	cout << endl << ret << endl;
	table.Remove(9);
	table.Print();

}
void TestString()
{
	HashTable<string, string> table(10);
	table.Insert("dict", "字典");
	table.Insert("hash", "雜湊");
	table.Insert("function", "函式");
	table.Insert("abcd", "函式");
	table.Insert("dcba", "函式");

	table.Print();
	bool ret = table.Find("function");
	cout << endl << ret << endl;
	table.Remove("hash");
	table.Print();
}
int main()
{
	//testInt();
	TestString();
	getchar();
	return 0;
}

測試結果: