笔记——哈希

负载因子

载荷因子

哈希冲突

闭散列

闭散列概念:

也叫开放定址法,当发生哈希冲突时,如果哈希表未被装满,说明在哈希表中必然还有 空位置,那么可以把key存放到冲突位置中的“下一个” 空位置中去。那如何寻找下一个空位置 呢?

用线性探测的方法:

先用key对数组大小取模,判断在下标为余数的位置上是否存在数据,如果存在则会查找下个元素是否存在,如果不存在就把数据存在此位置。存在就接着往下找

扩容条件:

当负载因子(哈希表元素个数和哈希表容量的比值)大于0.7

扩容方法:

在原数组进行扩容是不行的,不符合线性探测的规则,需要新建一个容量为原数组二倍的新数组

遍历原数组,按照线性探测的规则将数据拷贝到新数组里

插入数据:

插入数据之前需要判断是否需要扩容

在判断存储的位置,数据取模

数据个数自增1

元素状态改为存在(Exist)

删除数据:

先找到要删除的位置,对数据取模,判断元素状态(是否为 空,存在,还是删除)

如果找到状态为存在(Exist),把状态改为删除(delete)

哈希表数据个数自减1

查找数据

哈希表存的数据是pair<>类型,遍历哈希表,查找value值

代码部分

enum State
{
	Empty,
	Exist,
	Delete
};


template<class K, class V>
class HashElement
{
public:
	pair<K, V> _kv;
	State _state = Empty;
};


class _mapfun
{
public:
	int& operator()(int& data)
	{
		return data;
	}
	int operator()(string& data)
	{
		int sum = 0;
		std::string::iterator it = data.begin();
		while (it != data.end())
		{
			sum += *it;
			it++;
		}
		return sum;
	}
};

template<class K, class V, class mapfun = _mapfun >
class HashTable
{
public:
	typedef HashElement<K, V> HElement;

	vector<HashElement<K, V>> _arr;
	int _size = 0;
	HashTable()
	{
		_arr.resize(10);
	}

public:
	bool Insert(pair<K, V> data)
	{
		mapfun fun;
		//扩容
		if (_size * 10 / _arr.size() >= 7)
		{
			//创建新数组
			vector<HElement>newarr;
			newarr.resize(2 * _arr.size());
			int i = 0;
			for (i = 0; i < _arr.size(); i++)
			{
				if (_arr[i]._state == Exist)
				{

					//获取余数
					int remainer = fun(_arr[i]._kv.first) % newarr.size();
					if (newarr[remainer]._state == Empty)
					{
						newarr[remainer]._kv = _arr[i]._kv;
						newarr[remainer]._state = Exist;
					}
					else
					{
						while (1)
						{
							remainer++;
							if (remainer >= newarr.size())
								remainer = 0;
							if (newarr[remainer]._state == Empty)
							{
								newarr[remainer]._kv = _arr[i]._kv;
								newarr[remainer]._state = Exist;
								break;
							}
						}
					}
				}
			}
			swap(_arr, newarr);
		}

		int remainer = fun(data.first) % _arr.size();
		while (1)
		{
			if (_arr[remainer]._state == Empty)
			{
				_arr[remainer]._kv = data;
				_arr[remainer]._state = Exist;
				_size++;
				return 1;
			}
			remainer++;
			if (remainer >= _arr.size())
			{
				remainer = 0;
			}
		}
	}


	HElement* Find(K key)
	{
		int remainer = key % _arr.size();
		while (1)
		{
			if (_arr[remainer]._state == Exist && _arr[remainer]._kv.first == key)
			{
				return &_arr[remainer];
			}
			if (_arr[remainer]._state == Empty)
				return nullptr;
			remainer++;
		}
	}

	bool Erase(K key)
	{
		if (Find(key) == nullptr)
		{
			return 0;
		}
		HElement* e = Find(key);
		e->_state = Delete;
		return 1;
	}

};

开散列

开散列概念

发生哈希冲突时,把数据存在链表的下一位(或者是头都可以),首先还是要取模得到余数,找到要存的位置

也就是说哈西表元素是由链表构成的,

扩容方法

负载因子大于0.7时进行扩容,元素个数指的是所有链表中元素个数,哈希表的容量是能存多少链表的数量

创建新数组,容量为原先的二倍,进行数据转移

遍历原数组按照取模规则存到新数组,而为了减少删除和创建链表的消耗,把原数组链表节点连到新数组

代码部分

template<class K, class V>
class HashElement
{
public:
	HashElement() = default;
	pair<K, V> _kv;
	HashElement<K, V>* _next=nullptr;
	//State _state = Empty;
	HashElement(pair<K,V>data)
	{
		_kv = data;
	}
};


class _mapfun
{
public:
	int& operator()(int& data)
	{
		return data;
	}
	int operator()(string& data)
	{
		int sum = 0;
		std::string::iterator it = data.begin();
		while (it != data.end())
		{
			sum += *it;
			it++;
		}
		return sum;
	}
};

template<class K, class V, class mapfun = _mapfun >
class HashTable
{
public:
	typedef HashElement<K, V> HElement;

	vector<HashElement<K, V>*> _arr;
	int _size = 0;
	HashTable()
	{
		_arr.resize(10);
	}

public:
	bool Insert(pair<K, V> data)
	{
		//判断扩容
		if (_size * 10 / _arr.size()>=7)
		{
			int i = 0;
			vector<HElement*> newtable;
			newtable.resize(2 * _arr.size());
			for (i = 0; i < _arr.size(); i++)
			{
				HElement* cur = _arr[i];
				while (cur)
				{
					int remainer = cur->_kv.first % newtable.size();
					if(newtable[remainer] == nullptr)
					{
						newtable[remainer] = cur;
						newtable[remainer]->_next = nullptr;
						cur = cur->_next;
					}
					else
					{
						HElement* next = cur->_next;
						cur->_next = newtable[remainer];
						newtable[remainer] = cur;
						cur = next;
					}					
				}
			}			
			swap(_arr, newtable);
			return 1;
		}
		int remainer = data.first % _arr.size();
		if (_arr[remainer] == nullptr)
		{
			_arr[remainer] = new HElement(data);
		}
		else
		{
			HElement* newnode = new HElement(data);
			newnode->_next = _arr[remainer];
			_arr[remainer] = newnode;
		}
		_size++;
	}


	HElement* Find(K key)
	{
		int remainer = key % _arr.size();
		HElement* cur = _arr[remainer];
		while (cur)
		{
			if (cur->_kv.first == key)
				return cur;
			else
				cur = cur->_next;
		}
		return nullptr;
	}




	bool Erase(K key)
	{
		if (Find(key) == nullptr)
		{
			return 0;
		}
		HElement* e = Find(key);
		int remainer = key % _arr.size();
		if (_arr[remainer] == e)
		{
			HElement* head = _arr[remainer];
			_arr[remainer] = head->_next;
			delete head;
			return 1;
		}
		HElement* cur=_arr[remainer];
		while (cur)
		{
			if (cur->_next == e)
				break;
			cur = cur->_next;
		}
		cur->_next = e->_next;
		delete e;
		return 1;
	}

};

  • 13
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
哈希图像检索是一种用于在大规模图像数据库中快速搜索相似图像的方法。在哈希图像检索中,图像被转换为哈希码,然后通过比较哈希码的相似性来确定图像之间的相似度。有几种常用的哈希算法可以用于图像检索,如SIFT、SURF、ORB等特征提取算法\[1\]。此外,还有一些基于哈希的图像检索方法,如VLAD、BOF等,可以用于处理海量数据的图像检索\[1\]。 在哈希图像检索中,可以使用不同的方法来计算图像之间的相似度。一种常用的方法是通过比较图像的颜色、纹理和局部特征来计算相似度\[2\]。另外,还可以使用KD-Tree、局部敏感哈希(LSH)和原子哈希函数等方法来在高维空间中进行图像检索\[2\]。 此外,还有一种基于监督学习和核的Hash算法,称为KSH算法。KSH算法利用核主要是为了解决线性不可分问题,通过监督学习来学习到更有区分度的哈希值,从而降低特征维数\[3\]。 总之,哈希图像检索是一种用于在大规模图像数据库中快速搜索相似图像的方法,它可以通过提取图像特征和计算相似度来实现。不同的哈希算法和方法可以用于不同的图像检索任务。 #### 引用[.reference_title] - *1* *3* [图像检索传统算法学习笔记](https://blog.csdn.net/qq_39858278/article/details/83895342)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [8月23日计算机视觉理论学习笔记——图像检索](https://blog.csdn.net/Ashen_0nee/article/details/126467437)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

earthwormer

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值