一个简单的Hopscotch Hash

本文介绍了一个基于Hopscotch Hashing的实现,包括类结构、哈希表的初始化、插入、查找、删除等操作。它使用了自定义的哈希函数、线性探测和跳跃距离计算来处理冲突,并在装载因子过高时进行扩容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

pragma once
#include<vector>
#include<array>

using std::vector;
bool readInfo(size_t data, size_t bit);
bool isPrime(int n);
int nextPrime(int n);


template <typename T>
class HopscotchHash
{
public:
	explicit HopscotchHash(size_t size = 101, size_t dist = 32) :MAX_DIST(dist), currentSize(0), array(nextPrime(size)), MAX_LOAD(0.5) { MAXNUM =(1<<MAX_DIST-1)+(1<<MAX_DIST-1)-1; makeEmpty(); }
	HopscotchHash(const HopscotchHash & hh) :MAX_LOAD(hh.MAX_LOAD)
	{ 
		array = hh.array;
		currentSize = hh.currentSize; 
		MAX_DIST = hh.MAX_DIST; 
		MAXNUM = hh.MAXNUM;
	}
	void makeEmpty()
	{
		currentSize = 0;
		for (auto & entry : array)
		{
			entry.isActive = false;
			entry.hop = 0;
		}
	}
	bool contains(const T & xx) const
	{
		return findPos(xx) != -1;
	}
	bool insert(const T & x)
	{
		if (contains(x))
			return false;
		if (currentSize >= array.size()*MAX_LOAD)
			expand();
		return insertHelper(x);
	}
	bool insert(T & x)
	{
		if (contains(x))
			return false;
		if (currentSize >= array.size()*MAX_LOAD)
			expand();
		return insertHelper(x);
	}
	bool remove(const T & x)
	{
		if (!contains(x))
			return false;
		return removehelper(x);
	}

	T & lookup(T & x)
	{
		return array[findPos(x)].element;
	}

	const T & lookup(const T & x)
	{
		return array[findPos(x)].element;
	}
	HopscotchHash & operator=(const HopscotchHash & t)
	{
		if (this == &t)
			return *this;
		array = t.array;
		MAX_DIST = t.MAX_DIST;
		currentSize = t.currentSize;
		MAXNUM = t.MAXNUM;
		return *this;
	}

	size_t size() const
	{
		return array.size();
	}

private:
	struct HashEntry
	{
		T element;
		size_t hop;
		bool isActive;
		HashEntry() :isActive(0),hop(0) {}
		explicit HashEntry(const T & ele, int hpval = 0, bool act = false) :element(ele), hop(hpval), isActive(act) {}
	};
	vector<HashEntry> array;
	const double MAX_LOAD;
	size_t currentSize;
	size_t MAX_DIST;
	size_t MAXNUM;

	bool insertHelper(const T & xx)
	{
		size_t hashpos = myhash(xx);
		if (array[hashpos].hop == MAXNUM)
		{
			return failinsert(xx);
		}
		size_t emptypos = linearscope(xx, hashpos);
		bool changed = false;
		while (distance(hashpos, emptypos) >= MAX_DIST )
		{
			changed = false;
			for (size_t i = 1;!changed; i++)
			{
				if (i >= MAX_DIST)
				{
					return failinsert(xx);
				}
				size_t currentpos = movebackward(emptypos, i);
				for (size_t bs = 0; bs < i&&!changed; bs++)
				{
					if (readInfo(array[currentpos].hop, bs))
					{
						size_t temppos = movefoward(currentpos, bs);
						std::swap(array[emptypos].element, array[temppos].element);
						array[emptypos].isActive = true;
						array[temppos].isActive = false;
						writetrue(array[currentpos].hop, distance(currentpos,emptypos));
						writefalse(array[currentpos].hop, bs);
						emptypos = temppos;
						changed = true;
		
					}
				}
			}
		}
		array[emptypos].element=xx;
		array[emptypos].isActive = true;
		writetrue(array[hashpos].hop, distance(hashpos, emptypos));
		currentSize++;
		return true;

	}

	bool failinsert(const T & xx)
	{
		expand();
		return insert(xx);
	}
	bool failinsert(T && xx)
	{
		expand();
		return insert(xx);
	}
	bool insertHelper(T && xx)
	{
		size_t hashpos = myhash(xx);
		size_t emptypos = linearscope(xx,hashpos);
		if (array[hashpos].hop == MAXNUM)
			return failinsert(xx);
		bool changed = false;
		while (distance(hashpos, emptypos) >= MAX_DIST)
		{
			changed = false;
			for (size_t i = 1; !changed; i++)
			{
				if (i >= MAX_DIST)
					return failinsert(xx);
				size_t currentpos = movebackward(emptypos, i);
				for (size_t bs = 0; bs < i && !changed; bs++)
				{
					if (readInfo(array[currentpos].hop, bs))
					{
						size_t temppos = movefoward(currentpos, bs);
						std::swap(array[emptypos].element, array[temppos].element);
						array[emptypos].isActive = true;
						array[temppos].isActive = false;
						writetrue(array[currentpos].hop, distance(currentpos, emptypos));
						writefalse(array[currentpos].hop, bs);
						emptypos = temppos;
						changed = true;
					}
				}
			}
		}
		array[emptypos].element = xx;
		array[emptypos].isActive = true;
		std::swap(array[emptypos].element, xx);
		writetrue(array[hashpos].hop, distance(hashpos, emptypos));
		currentSize++;
		return true;

	}

	size_t & writetrue(size_t  & hop, size_t bias)
	{
		size_t sentinel = 1;
		sentinel  <<= bias;
		hop|=sentinel;
		return hop;
	}


	void writefalse(size_t & hop, size_t bias)
	{
		size_t sentinel = 1;
		sentinel <<= bias;
		sentinel = ~sentinel;
		hop &= sentinel;
	}

	size_t distance(size_t front, size_t rear)
	{
		if (front <= rear)
			return rear - front;
		else
			return array.size()-front+rear ;
	}

	size_t linearscope(const T & xx,size_t hashpos) const
	{
		size_t i = 0;
		while (i < array.size())
		{
			size_t bs = movefoward(hashpos, i);
			if (!isActive(bs))
				return bs;
			++i;
		}
		return -1;
	}

	
	bool isActive(int currentPos) const
	{
		return array[currentPos].isActive;
	}

	size_t myhash(const T & x) const
	{
		static std::hash<T> hf;
		return hf(x) %array.size();
	}

	bool removehelper(const T & x)
	{
		size_t hashpos = myhash(x);
		size_t datapos = findPos(x,hashpos);
		size_t bs = distance(hashpos, datapos);
		writefalse(array[hashpos].hop, bs);
		array[datapos].isActive = false;
		currentSize--;
		return true;
	}
	void rehash()
	{
		auto oldLists = array;

		// Create new double-sized, empty table
		array.resize(nextPrime(2 * array.size()));
		makeEmpty();
		// Copy table over
		currentSize = 0;
		for (auto & Entry : oldLists)
			if(Entry.isActive)
				insert(std::move(Entry.element));
	}

	void expand()
	{
		rehash();
	}



	
	size_t movefoward(size_t pos,size_t bias) const
	{
		pos +=bias;
		if (pos < array.size())
			return pos;
		else
			return pos-array.size();
	}
	size_t movebackward(size_t pos,size_t bias) const
	{
		if (bias > pos)
			return array.size() + pos - bias;
		else
			return pos - bias;
	}
	size_t findPos(const T & xx) const
	{
		size_t pos = myhash(xx);
		return findPos(xx, pos);

	}

	size_t findPos(const T & xx,size_t hashpos) const
	{
		size_t CurrentPos = 0;
		for (size_t i = 0; i < MAX_DIST; i++)
		{
			if (readInfo(array[hashpos].hop, i))
			{
				CurrentPos = movefoward(hashpos, i);
				if (array[CurrentPos].element == xx)
					return CurrentPos;
			}
		}
		return -1;

	}
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值