C++ 哈希表 线性探测 二次探测 哈希桶

#pragma once

#include<iostream>//含一次探测  二次探测
#include<vector>
#include<math.h>

using namespace std;

enum Status
{
	EXIST,
	EMPTY,
	DELET,
};

template <class K,class V> //key/value形式结构体
struct KV
{
	K _key;
	V _value;
	KV(const K& key = K(), const V& value = V())
		:_key(key)
		, _value(value)
	{}
};

template <class K, class V>
class HashTable
{
public:
	KV<K,V>* _tables;
	size_t _size;
	size_t _capacity;
	Status* _status;

public:
	HashTable()
		:_tables(NULL)
		,_size(0)
		, _capacity(0)
		, _status(NULL)
	{}
	void  Insert(const K& key , const V& value )
	{
		if (_capacity == 0 || _size * 10 / _capacity > 7)
		{
			if(!_IncreaseCapacity())
				cout<<"线性探测散列表已满"<<endl;
		}

		size_t i = _HashFanction1(key);
		do
		{

			if (key == _tables[i]._key&&_status[i]==EXIST)
					break;
			if (_status[i] != EXIST)
			{
				_tables[i]._key = key;
				_tables[i]._value = value;
				_status[i] = EXIST;
				++_size;
				break;
			}
			else if (++i >= _capacity)
				i = 0;
		} while (1);

	}

	void  Insert2(const K& key, const V& value)
	{
		if (_capacity == 0 || _size * 10 / _capacity > 7)
		{
			if (!_IncreaseCapacity())
				cout << "线性探测散列表已满" << endl;
		}
		int count = 0;//二次探测的计数器
		size_t i = _HashFanction2(key,count);
		do
		{
			if (i<0)
				i = _capacity + i;
			if (key == _tables[i]._key&&_status[i] == EXIST)
				break;
			if (_status[i] != EXIST)
			{
				_tables[i]._key = key;
				_tables[i]._value = value;
				_status[i] = EXIST;
				++_size;
				break;
			}
			else 
				i = _HashFanction2(key, i);
		} while (1);

	}

	int Find(const K& key)
	{
		size_t i = _HashFanction1(key);
		size_t j = i;
		do
		{

			if (_status[i] == EXIST&&key==_tables[i]._key)
			{

				return i;
			}
			else if (++i >= _capacity)
				i = 0;
		} while (i!=j);
		return -1;

	}

	void Remove(const K& key)
	{
		size_t i = _HashFanction1(key);
		size_t j = i;
		do
		{

			if (_status[i] == EXIST&&key == _tables[i]._key)
			{
				_status[i] = DELET;
				break;
			}
			else if (++i >= _capacity)
				i = 0;
		} while (i != j);
	}

	void print()
	{
		size_t i = 0;
		for (; i < _capacity; ++i)
		{
			printf("[%d] K: %d  V: %d S: %d \n",i, _tables[i]._key, _tables[i]._value, _status[i]);
		}
	}

protected:
	size_t _HashFanction1(const K& key)//一次探测 (线性探测)
	{

		return key%_capacity;
	}

	int _HashFanction2(const K& key,const int i)//二次次探测 (防止数据积累在一块内存)
	{

		return (key+(int)pow(-1,i)*i*i)%_capacity;
	}

	bool _IncreaseCapacity()
	{
		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 (_PrimeList[i]>_capacity)
			{
				size_t newCapacity = _PrimeList[i];
				HashTable<K, V> newHash;
				newHash._tables = new KV<K,V>[newCapacity];
				newHash._status = new Status[newCapacity];
				newHash._capacity=_PrimeList[i];
				for (size_t j = 0; j < newCapacity; ++j)
				{
					if (_status&&j<_capacity&&_status[j] == EXIST)
					{
						//newHash.Insert(_tables[j]._key, _tables[j]._value);//一次探测的增容调一次探测的插入函数
						newHash.Insert2(_tables[j]._key, _tables[j]._value);//二次探测。。。。。。
					}
					else
					{
						newHash._status[j] = EMPTY;
						newHash._tables[j]._key = 0;
						newHash._tables[j]._value = 0;
					}

				}
				swap(_tables, newHash._tables);
				swap(newHash._status,_status);
				swap(newHash._capacity, _capacity);

				return true;
			}
		}
		return false;

	}

};

#pragma once

#include<iostream>//哈希桶
#include<vector>
#include<math.h>
#include<string>

using namespace std;

template <class K>
class GetKey
{
public:
	size_t operator()(const K& key)
	{
		return key;
	}
};

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);
}

template <>
class GetKey<string>
{
public:
	size_t operator()(const string & key)
	{
		return BKDRHash(key.c_str());
	}
};
template <class K,class V> //key/value形式结构体
struct KeyValue
{
	K _key;
	V _value;
	KeyValue<K, V>* _next;
	KeyValue(const K& key = K(), const V& value = V())
		:_key(key)
		, _value(value)
		, _next(NULL)
	{}
};

template <class K, class V>
class HashBucket
{
public:
	vector<KeyValue<K, V>*> _tables;
	size_t _size;

public:
	HashBucket()
		:_size(0)
	{}
	void  Insert(const K& key , const V& value )
	{
		if (_tables.capacity()==0|| _size * 10 / _tables.capacity() > 7)
		{
			if(!_IncreaseCapacity())
				cout<<"线性探测散列表已满"<<endl;
		}

		size_t i = _HashFanction1(key);
		KeyValue<K, V>* cur = _tables[i];
		if (cur == NULL)
			_tables[i] = new KeyValue<K, V>(key, value);
		else
		{
			while (cur)
			{

				if (cur->_key == key)
					return;
				else if (cur->_next == NULL)
					break;
				else
					cur = cur->_next;
			}
			cur->_next = new KeyValue<K, V>(key, value);
		}
		++_size;
	}

	int Find(const K& key)
	{
		size_t i = _HashFanction1(key);
		KeyValue<K, V>* cur = _tables[i];
		while (cur)
		{
			if (cur->_key == key)
				return i;
			cur = cur->_next;
		}
		return -1;

	}

	void Remove(const K& key)
	{
		size_t i = _HashFanction1(key);
		KeyValue<K, V> * cur =_tables[i];
		KeyValue<K, V> * prev = NULL;

		while (cur)
		{
			if (cur->_key == key)
			{
				if (prev)
				{
					prev->_next = cur->_next;
				}
				else
					_tables[i] = NULL;
					delete cur;
					return;
			}
			prev = cur;
			cur = cur->_next;

		}
	}

	void print()
	{
		size_t i = 0;
		for (; i < _tables.capacity(); ++i)
		{
			KeyValue<K, V>* cur = _tables[i];

			if (cur == NULL)
				//printf("[%d]:K= %d V= %d ->", i, -1,-1);
				cout<< "[" << i << "] "<< -1 << " " << -1 << " " << "->";
			while (cur)
			{

				//printf("[%d]:K= %d V= %d ", i, cur->_key,cur->_value);
				cout << "[" << i << "] "<< _tables[i]->_key << " " << _tables[i]->_value << " " << "->";

				cout << "->";
				cur = cur->_next;
			}
			cout <<" NULL"<<endl;
		}

	}

protected:
	size_t _GetKey(const K& key)
	{
		return GetKey<K>()(key);
	}
	size_t _HashFanction1(const K& key)//一次探测 (线性探测)
	{
		size_t k = _GetKey(key);
		return k%_tables.capacity();
	}

	bool _IncreaseCapacity()
	{
		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 (_PrimeList[i]>_tables.size())
			{
				size_t newCapacity = _PrimeList[i];
				vector<KeyValue<K, V>*> newtables;
				newtables.resize(newCapacity, 0);
				for (size_t j = 0; j < _tables.capacity(); ++j)
				{
					KeyValue<K, V>* cur = _tables[j];
					while (cur)
					{
						size_t k = _HashFanction1(cur->_key);

						KeyValue<K, V>* tmp = cur;
						KeyValue<K, V>* tmp2 = newtables[k];
						if (tmp2 = NULL)
						{
							newtables[i] = cur;
							break;
						}
						while (tmp2->_next)
						{
							tmp2->_next = cur;
						}
						tmp->_next = cur;
						cur->_next = NULL;
						  _tables[j] = tmp;
					   cur = tmp;
					}

				}
				swap(newtables, _tables);
			}
			return true;
		}
	return false;

}

};

#include"hashtable.hpp" //测试用例
#include"hashbucket.hpp"

using namespace std;

void test()
{

	HashTable<int, int> h1;

	for (int i = 0; i <30;++i)
		h1.Insert(i, i);
	h1.Insert(100,1);
	h1.Insert(170, 3);
	h1.Insert(223, 5);
	h1.Insert(56, 7);
	h1.Insert(550,9);
	h1.print();
	cout<<h1.Find(223)<<endl;
	cout << h1.Find(224) << endl;
	h1.Remove(56);
	h1.Remove(58);

	h1.print();

}

void test2()
{

	HashTable<int, int> h1;

	for (int i = 0; i < 30;++i)
	h1.Insert(i, i);
	h1.Insert2(100, 1);
	h1.Insert2(170, 3);
	h1.Insert2(223, 5);
	h1.Insert2(56, 7);
	h1.Insert2(550, 9);
	h1.print();
	cout << h1.Find(223) << endl;
	cout << h1.Find(224) << endl;
	h1.Remove(56);
	h1.Remove(58);

	h1.print();
}

void test3()
{
	HashBucket<int, int>  h1;
	h1.Insert(1,1);
	h1.Insert(3, 3);
	h1.Insert(5, 5);
	h1.Insert(7, 7);
	h1.Insert(54, 54);
	h1.Insert(107, 107);
	for (int i = 0; i < 99;i+=2)
		h1.Insert(i, i);

	h1.print();
	cout<<h1.Find(1)<<endl;
	cout<<h1.Find(107)<<endl;
	cout << h1.Find(5) << endl;

	h1.Remove(54);
	h1.print();

}
void test4()
{
	HashBucket<string, string>  h1;
	h1.Insert("裴培华", "帅哥");
	h1.Insert("农文彤", "大屌");
	h1.Insert("鸭仔", "舎宝");
	h1.Insert("童坤坤", "学霸");
	h1.print();
	cout<<h1.Find("裴培华")<<endl;
	h1.Remove("农文彤");
	h1.print();

}

int main()
{
	//test();
	//test2();
	//test3();
	test4();
	return 0;
}
时间: 2024-12-27 19:33:44

C++ 哈希表 线性探测 二次探测 哈希桶的相关文章

哈希表---线性探测再散列(hash)

//哈希表---线性探测再散列 #include <iostream> #include <string> #include <stdio.h> #include <string.h> #define m 10000 #define NULLkey -1 using namespace std; int HashTable[m]; int Hash_search( int k) { int p0, pi; p0=hash(k); //函数运算值 if(Has

哈希表线性探测

HashTable-散列表/哈希表,是根据关键字(key)而直接访问在内存存储位置的数据结构. 它通过一个关键值的函数将所需的数据映射到表中的位置来访问数据,这个映射函数叫做散列函数,存放记录的数组叫做散列表. 哈希冲突/哈希碰撞 不同的Key值经过哈希函数Hash(Key)处理以后可能产生相同的值哈希地址,我们称这种情况为哈希冲突.任意的散列函数都不能避免产生冲突. 我给大家介绍的是哈希表的线性探测,线性探测的基本思路: 1.用一个数据除以散列表的长度,余数是多少,就把这个数放在散列表下标相同

哈希表——线性探测法、链地址法、查找成功、查找不成功的平均长度

一.哈希表 1.概念 哈希表(Hash Table)也叫散列表,是根据关键码值(Key Value)而直接进行访问的数据结构.它通过把关键码值映射到哈希表中的一个位置来访问记录,以加快查找的速度.这个映射函数就做散列函数,存放记录的数组叫做散列表. 2.散列存储的基本思路 以数据中每个元素的关键字K为自变量,通过散列函数H(k)计算出函数值,以该函数值作为一块连续存储空间的的单元地址,将该元素存储到函数值对应的单元中. 3.哈希表查找的时间复杂度 哈希表存储的是键值对,其查找的时间复杂度与元素数

Java解决Hash(散列)冲突的四种方法--开放地址法(线性探测,二次探测,伪随机探测)、链地址法、再哈希、建立公共溢出区

最近时间有点紧,暂时先放参考链接了,待有时间在总结一下: 查了好多,这几篇博客写的真心好,互有优缺点,大家一个一个看就会明白了: 参考 1. 先看这个明白拉链法(链地址法),这个带源码,很好看懂,只不过是只讲了拉链法一种: 2. 再看这个比较全的,四种全讲了,链接,这篇比较形象,有图.但是这两篇都没有仔细介绍优缺点: 3. 最后看优缺点,点击这里: 原文地址:https://www.cnblogs.com/gjmhome/p/11372883.html

线性探针法哈希表

2019-07-03  11:40:23 import java.io.ObjectInputStream; import java.util.ArrayList; /** * @ClassName LinearProbeHashST * @Author wangyudi * @Date 2019/7/3 10:53 * @Version 1.0 * @Description 用线性试探法实现哈希表 */ public class LinearProbeHashST<Key, Value> {

哈希表的理解

哈希表是种数据结构,它可以提供快速的插入操作和查找操作.第一次接触哈希表时,它的优点多得让人难以置信.不论哈希表中有多少数据,插入和删除(有时包括侧除)只需要接近常量的时间即0(1)的时间级.实际上,这只需要几条机器指令. 对哈希表的使用者一一人来说,这是一瞬间的事.哈希表运算得非常快,在计算机程序中,如果需要在一秒种内查找上千条记录通常使用哈希表(例如拼写检查器)哈希表的速度明显比树快,树的操作通常需要O(N)的时间级.哈希表不仅速度快,编程实现也相对容易. 哈希表也有一些缺点它是基于数组的,

【转】 哈希表

哈希表是种数据结构,它可以提供快速的插入操作和查找操作.第一次接触哈希表时,它的优点多得让人难以置信.不论哈希表中有多少数据,插入和删除(有时包括侧除)只需要接近常量的时间即0(1)的时间级.实际上,这只需要几条机器指令. 对哈希表的使用者一一人来说,这是一瞬间的事.哈希表运算得非常快,在计算机程序中,如果需要在一秒种内查找上千条记录通常使用哈希表(例如拼写检查器)哈希表的速度明显比树快,树的操作通常需要O(N)的时间级.哈希表不仅速度快,编程实现也相对容易. 哈希表也有一些缺点它是基于数组的,

数据结构 之 哈希表

1.什么是哈希表? 哈希表是一种数据结构,它可以提供快速的插入和删除操作.如果存储在哈希表中的数据较好的满足了哈希表的要求,那么在哈希表中执行插入和操作只需要接近常量的时间,即时间复杂度为o(1),但哈希表也不是十全十美的,它也存在着缺点,这都会在下面慢慢谈到. 2.哈希表的存储方式 哈希表是通过数组来存储数据的,但数据并不是直接放入数组中(直接放入就是数组存储啦!).说到这里就需要谈到哈希化,而哈希表的核心部分,我认为就是哈希化了:简而言之,将数据插入哈希表中的数组的相应位置的规则,就是哈希化

数据结构与算法分析:哈希表

以下是阅读了<算法导论>后,对哈希表的一些总结: 哈希表又叫散列表,是实现字典操作的一种有效数据结构.哈希表的查询效率极高,在没有冲突(后面会介绍)的情况下可做到一次存取便能得到所查记录,在理想情况下,查找一个元素的平均时间为O(1)(最差情况下散列表中查找一个元素的时间与链表中查找的时间相同:O(n),但实际情况中一般散列表的性能是比较好的). 哈希表就是描述key-value对的映射问题的数据结构,更详细的描述是:在记录的存储位置和它的关键字之间建立一个确定的对应关系h,使每个关键字与哈希