哈希开链法实现

哈希表在对于查找方面是很快捷方便的,哈希是一个映射,对于关键字映射在哈希表里的位置是随机的,但也是有要求的,对于关键字的映射不能超出表的范围。


但对于不同的关键字,可能会映射到同一个哈希位置上,这样就会产生哈希冲突。哈希冲突只能尽可能的减少,但是不能避免。

处理哈希冲突的方法:

1、开放定址法
该处理方法有线性探测再散列和二次探测再散列两种处理方式,前者是将出现的冲突进行+1,如果下一个仍旧冲突,在原本的位置上+2,以此类推,直到找到一个位置为空的位置上将关键字放上,后者则是在出现冲突之后加上一次的平方,若之后的位置上仍然出现冲突,则在原本的位置上向后移动2的平方,冲突几次就是几的平方。

2、链地址法

将所有的相同性质的关键字放在同一条线性链表上,即在哈希表的每个地址下面挂上一条链表。一般情况下我们不会一下子去把空间开的超级大,所以存在扩容这些,那么就可以考虑vector来实现,只不过每个元素装的是一个链表。

开链法实现如下:


//拉链法哈希表实现
namespace HASH_BUCKET
{
	template<class V>
	struct HashNode
	{
		V _v;
		//ValueType _valueField;

		HashNode<V>* _next;

		HashNode(const V& v)
			:_v(v)
			, _next(NULL)
		{}
	};

	template<class K, class V,class KeyOfValue>
	class HashTable
	{
		typedef V ValueType;
		typedef HashNode<V> Node;

	public:

		HashTable()
			:_size(0)
		{}
		//插入,无法插入重复的
		bool Insert(const ValueType& valueField)
		{
			KeyOfValue kov;
			CheckCapacity();//检查容量是否足够
			size_t index = HashFunc(kov(valueField), _tables.size());//计算定位的位置
			Node* cur = _tables[index];//取得当前未插入的结点的位置
			while (cur)
			{
				if (kov(cur->_v) == kov(valueField))
					return false;
				cur = cur->_next;
			}
			Node* node = new Node(valueField);//创建该节点
			node->_next = _tables[index];//将该结点挂在对应的位置下面
			_tables[index] = node;
			++_size;
			return true;
		}
		void CheckCapacity()
		{
			KeyOfValue kov;
			//如果size等于0则第一次开辟空间为10
			if (_tables.size() == 0)
			{
				_tables.resize(10,NULL);
			}
			else if (_size==_tables.size())
			{
				size_t newsize = _tables.size() * 2;
				vector<Node*> newtables;
				newtables.resize(newsize, NULL);
				for (size_t i = 0; i < _tables.size(); i++)
				{
					Node* cur = _tables[i];
					while (cur)
					{
						size_t index = HashFunc(kov(cur->_v), newsize);
						Node* next = cur->_next;
						cur->_next = newtables[index];
						newtables[index] = cur;
						cur = next;
					}
					_tables[i] = NULL;
				}
				_tables.swap(newtables);
			}
		}
		bool Find(const K& key)
		{
			KeyOfValue kov;
			size_t index = HashFunc(key);
			Node* cur = _tables[index];
			while (cur)
			{
				if (kov(cur->_v) == key)
					return true;
				cur = cur->_next;
			}
			return false;
		}
		bool Rremove(const K& key)
		{
			size_t index = HashFunc(key);
			KeyOfValue kov;
			Node* cur = _tables[index];
			while (cur!=NULL)
			{
				if (kov(cur->_v) == key)
				{
					_tables[index] = cur->_next;
					delete cur;
					return true;
				}
				else
				{
					Node* prev = cur;
					cur = cur->_next;
					while (cur)
					{
						if (kov(cur->_v) == key)
						{
							prev->_next = cur->_next;
							delete cur;
							return true;
						}
						cur = prev;
						cur = cur->_next;
					}
					return false;
				}
			}
			return false;
		}
		size_t HashFunc(const K& key)
		{
			return key%_tables.size();
		}
		size_t HashFunc(const K& key, size_t size)
		{
			return key % size;
		}
	private:
		vector<Node*> _tables;
		size_t _size;//表的大小
	};
	template<class K,class V>
	struct MapKeyOfValue
	{
		const K& operator()(const pair<K, V>& kv)
		{
			return kv.first;
		}
	};
	template<class K>
	struct SetKeyOfValue
	{
		const K& operator()(const K& key)
		{
			return key;
		}
	};
	void test()
	{
		HashTable<int, int, SetKeyOfValue<int>> table;
		table.Insert(10);
		table.Insert(54);
		table.Insert(22);
		table.Insert(22);
		table.Insert(23);
		table.Insert(53);
		table.Insert(82);

		cout << table.Find(22) << endl;
		cout << table.Find(199) << endl;
		cout << table.Find(54) << endl;
		cout << table.Find(23) << endl;
		cout << table.Find(82) << endl;
		cout << table.Find(10) << endl;
		cout << table.Find(53) << endl;

		cout << table.Rremove(53) << endl;
		cout << table.Rremove(22) << endl;
		cout << table.Rremove(199) << endl;
		cout << table.Rremove(54) << endl;
		cout << table.Rremove(23) << endl;

	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值