哈希表线性探测&二次探测

在代码中实现了哈希表中任意类型都可以存放,即哈希函数要可扩展以及哈希表动态增容的功能。

贴上代码:

#include<iostream>
#include<vector>
using namespace std;

template<class K>//特化
 class _HashFun
 {
 public:
	 size_t operator()(K key)
	 {
		 return key;
	 }
 };

 template<>
 class _HashFun<string>
 {
 public:
	 size_t operator()(const char* str)
	 {
		 return BKDRHash(str);
	 }
 private:
	 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);
  }
 };

enum State //状态标志
{
	EXIST,
	EMPTY,
	DELETE,
};

template<class K, class V>
struct HashElem //哈希元素
{
	HashElem()
		:_s(EMPTY)
	{}
	pair<K, V> _kv;
	State _s;
};

template<class K, class V, class HashFunc = _HashFun<K>, bool Isline = true>
class HashTable //哈希表
{
public:
	HashTable(size_t size = 12)
		:_size(0)
	{
		_table.resize(size);
	}

	bool Insert(const K& key, const V& value)
	{
		_CheckTable();
		//如果表满
		if(_size == _table.size())
			return false;

        size_t hashAddr = _HashFunc(key);//找哈希地址
		size_t H0 = hashAddr;
		size_t i = 1;
 		while(EXIST == _table[hashAddr]._s)//冲突
		{
			if(key == _table[hashAddr]._kv.first)//只插入唯一值
				return false;

			if(Isline)
			{
				hashAddr =  HashFunc1(H0);
			}
			else
			{
				hashAddr =  HashFunc2(H0, i);
			}
			i++;

		    //hashAddr++;//线性探测
			//if(hashAddr == _table.size())//找到最后一个再从头开始
			//	hashAddr = 0;
		}
		//插入
		_table[hashAddr]._kv.first = key;
		_table[hashAddr]._kv.second = value;
		_table[hashAddr]._s = EXIST;
		_size++;
		return true;

	}
	pair<HashElem<K,V>*, bool> Find(const K& key)//查找值为key的元素
	{
		size_t hashAddr = _HashFunc(key);
	    size_t H0 = hashAddr;
		size_t i = 1;
		while(EMPTY != _table[hashAddr]._s)
		{
			if(_table[hashAddr]._kv.first == key)
			{
				if(_table[hashAddr]._s == EXIST)
					return make_pair(&_table[hashAddr], true);
				else//DELETE
					return make_pair((HashElem<K, V>*)NULL, false);//这里需要强转,否则编译器可能将NULL当成0
			}
			if(Isline)
			{
				hashAddr =  HashFunc1(H0);
			}
			else
			{
				hashAddr =  HashFunc2(H0, i);
			}
			i++;
			//hashAddr++;//线性探测
			//if(hashAddr == _table.size())
			//	hashAddr = 0;
		}
		return make_pair((HashElem<K,V>*)NULL,false);
	}

	bool Remove(const K& key)//删除
	{
		pair<HashElem<K, V>*, bool> pos = Find(key);
		if(pos.second)
		{
			pos.first->_s = DELETE;
			_size--;
			return true;
		}
		return false;
	}

private:
	size_t _HashFunc(const K& key)
	{
		return HashFunc()(key) % 10/*_table.size()-1*/;
	}

	// 线性探测处理函数
	size_t HashFunc1(size_t hashAddr)
	{
		hashAddr++;
		if(hashAddr == _table.size())
			hashAddr = 0;
		return hashAddr;
	}

	// 二次探测处理函数
	size_t HashFunc2(size_t hashAddr, size_t i)
	{
		if(hashAddr >= _table.size())
			hashAddr = 0;
		return hashAddr+2*i+1;
	}

	void Swap(HashTable<K,V>& ht)
	{
		_table.swap(ht._table);//两个容器交换不创建临时对象 
		swap(_size, ht._size);
	}
	void _CheckTable()
	{
		if(_size*10 / _table.size() >= 7)
		{
			size_t newsize = _table.size()*2;//乘2可能会越界
			//newsize = GetNextPrime(newsize);
			//交换法 销毁原来的空间
			HashTable<K, V> ht(newsize);
			for(int idx = 0;idx <= _table.size();idx++)
			{
				if(_table[idx]._s == EXIST)
					ht.Insert(_table[idx]._kv.first, _table[idx]._kv.second);
			}
			Swap(ht);
		}
	}

	vector<HashElem<K, V>> _table;
	size_t _size;//有效元素的个数
};

void FunTest()
{
	int a[] = {11,25,37,14,36,49,57};
	HashTable<int, int> ht;
	for(int idx = 0; idx <sizeof(a)/sizeof(a[0]); idx++)
		ht.Insert(a[idx], idx);

	pair<HashElem<int, int>*, bool> pos = ht.Find(25);
	if(pos.second)
	{
		cout<<pos.first->_kv.first<<endl;
	}
	else
	{
		cout<<"没有找到该元素"<<endl;
	}

	ht.Remove(25);

	pair<HashElem<int, int>*, bool> pos1 = ht.Find(25);
	if(pos1.second)
	{
		cout<<pos1.first->_kv.first<<endl;
	}
	else
	{
		cout<<"没有找到该元素"<<endl;
	}

}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值