C++ 哈希

目录

哈希:

哈希表(散列表):

哈希函数:

哈希冲突:

 闭散列:

闭散列的结构: 

插入数据

查找元素

删除元素

开散列

哈希表结点

迭代器

迭代器结构:

operator++()

operator*()   operator->()   operator!=()

开散列的哈希表

哈希表的结构

仿函数

析构函数

begin()   end()

查找元素( Find() )

增加元素( Insert() )

删除元素( Erase() )

封装unordered_map和unordered_set​​​​​​​

unordered_set

unordered_map


哈希

通过某种函数(hashFunc)使元素的存储位置与它的关键码之间能够建立一一映射的关系,我们便可以通过映射关系很快的查找到想要的元素。

哈希表(散列表):

希表(散列表)是一种数据结构通过哈希(散列)方法,构造出来的结构称为哈希表(Hash Table)(或者称散列表),哈希表查找元素的时间复杂度是O(1)。

哈希函数:

通过哈希(散列)方法,哈希方法中使用的转换函数称为哈希(散列)函数。

常见的哈希函数:除留余数法:设哈希表中允许的地址数为m,插入的数据为key,则:

key(关键码对应的哈希地址) = key(关键码) %  m

例如:

 将要插入的数据先%数组的大小,找到对应的映射位置插入

哈希冲突:

当我们在插入13时,会发现13对应的位置已经有数据了,则就构成哈希冲突

解决哈希冲突两种常见的方法是:闭散列和开散列

 
闭散列:

闭散列:也叫开放定址法,当发生哈希冲突时,如果哈希表未被装满,说明在哈希表中必然还有空位置,那么通过线性探测,或二次探测的方法,找到key存放到冲突位置中的“下一个” 空位置去。

闭散列的结构: 


enum State //判断数组位置的状态
{
  EMPTY, //空
  EXITS,  //存在
  DELETE,  //删除
};

template<class T>
struct HashData
{
	T _data;
	State _state; //状态
};

template<class K, class T, class KeyOfT> //仿函数,取出数据的关键字
class HashTable
{
	typedef HashData<T> HashData;
public:
	bool Insert(const T& d); //增

	HashTable* Find(const K& key); //查

	bool Erase(const K& key); //改

private:
	vector<HashData> _tables;  //数组
	size_t _num = 0; //存了几个有效数据
};

哈希表中存放着一个数组(存放着结点)和有效数据的个数。

哈希表结点中存放的除了数据,还有一个被标记的状态,方便我们实现增删查改的操作。

插入数据

负载因子:负载因=表的数据/表的大小,衡量哈希表满的程度,表越接近满,插入数据越容易冲突,冲突越多,效率越低。

哈希表并不是满了才增容,开放定制法中,一般负载因子到0.7左右就开始增容

负载因子越小,冲突概率越低,整体效率越高,但是负载因子越小,浪费的空间越大

bool Insert(const T& data)
{
  KeyOfT koft;
  
  //表为空时增容,或者负载营造到0.7时增容,
  if(_tables.size()==0 || _num*10/_tables.size()>=7)
  {
        //定义一个哈希表的对象,将空间开成旧表的2倍
        HashTable<K, T, KeyOfT> newht;
		size_t newsize = _tables.size() == 0 ? 10 : _tables.size() * 2;
		newht._tables.resize(newsize);
        
        //遍历旧表的数据,在新表中调用Insert接口,将旧表的元素依次插入的新表
        for (size_t i = 0; i < _tables.size(); ++i)
		{
			if (_tables[i]._state == EXITS)
			{
				newht.Insert(_tables[i]._data);
			}

		}
        //将新表和旧表交换
		_tables.swap(newht._tables);     
  }

  //计算出data中的key在表中映射的位置
  size_t index = koft(data) % _tables.size();
  //找到空的位置
  while (_tables[index]._state == EXITS)
  { 
    //如果插入的元素表中已经有了,则返回false
    if(kofk(_tables[index]._date)==koft(data))
    {
       return false;
    }
    
    ++index;

    if(index==_tables.size())
    {
      index=0;
    }

  }

  //找到插入的位置
  _tables[index]._data
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值