iOS中用到的数据结构_哈希表

4,002 阅读4分钟

关键词:哈希表、weak、RunLoop、哈希冲突

哈希表(hash table,也叫散列表),是根据键(key)直接访问访问在内存储存位置的数据结构。

哈希表的关键思想是使用哈希函数​将键映射到存储桶​。更确切地说,
  1. 当我们插入一个新的键时,哈希函数将决定该键应该分配到哪个桶中,并将该键存储在相应的桶中;
  2. 当我们想要搜索一个键时,哈希表将使用相同的哈希函数来查找对应的桶,并只在特定的桶中进行搜索。

Hash在iOS中的应用

weak表 

weak表采用的是一个全局的HashMap嵌套数组的结构存储数据的,销毁对象(weak指针指向的对象)的时候,根据对象从HashMap中找到存放所有指向该对象的weak指针的数组,然后将数组中的所有元素都置为nil。
weak的最大特点就是在对象销毁的时候,自动置nil,减少访问野指针的风险,这也是设计weak的初衷。方案设计实现好后,weak指针置nil的基本步骤:
  1. 对象dealloc的时候,从全局的HashMap中,根据一个唯一代表对象的值作为key,找到存储所有指向该对象的weak指针的数组
  2. 将数组中的所有元素都置为nil

weak表结构及细节可以参考下图及链接

struct SideTable {
	// 保证原子操作的自旋锁
    spinlock_t slock;
    // 引用计数的 hash 表
    RefcountMap refcnts;
    // weak 引用全局 hash 表
    weak_table_t weak_table;
}


推荐阅读  www.desgard.com/weak/

Runloop

线程和 RunLoop 之间是一一(子线程可以没有)对应的,其关系是保存在一个全局的 Dictionary 里。线程刚创建时并没有 RunLoop,如果你不主动获取,那它一直都不会有。RunLoop 的创建是发生在第一次获取时,RunLoop 的销毁是发生在线程结束时。你只能在一个线程的内部获取其 RunLoop(主线程除外)。

推荐阅读 blog.ibireme.com/2015/05/18/…

其他

还有很多其他的点也用到了哈希表,可以参考下图


Hash的优势

  • 优点 :哈希表可以提供快速的操作。
  • 缺点 :哈希表通常是基于数组的,数组创建后难于扩展。 也没有一种简便的方法可以以任何一种顺序〔例如从小到大)遍历表中的数据项。
综上,如果不需要有序遍历数据,井且可以提前预测数据量的大小。那么哈希表在速度和易用性方面是无与伦比的。

Hash常见问题及解法

哈希冲突

当关键字值域远大于哈希表的长度,而且事先并不知道关键字的具体取值时。冲突就难免会发 生。另外,当关键字的实际取值大于哈希表的长度时,而且表中已装满了记录,如果插入一个新记录,不仅发生冲突,而且还会发生溢出
  1. 用开放定址法解决冲突的做法是:当冲突发生时,使用某种探查(亦称探测)技术在散列表中形成一个探查(测)序列。沿此序列逐个单元地查找,直到找到给定 的关键字,或者碰到一个开放的地址(即该地址单元为空)为止(若要插入,在探查到开放的地址,则可将待插入的新结点存人该地址单元)。查找时探查到开放的 地址则表明表中无待查的关键字,即查找失败。
  2. 拉链法解决冲突的做法是:将所有关键字为同义词的结点链接在同一个单链表中。若选定的散列表长度为m,则可将散列表定义为一个由m个头指针组成的指针数 组T[0..m-1]。凡是散列地址为i的结点,均插入到以T[i]为头指针的单链表中。T中各分量的初值均应为空指针。在拉链法中,装填因子α可以大于 1,但一般均取α≤1。

存在重复元素(leetcode题目)

基本就是使用哈希表来查重

两数之和(leetcode题目)

使用哈希表在数组中找出