这个是第一篇, 说一下前提;
前些时候用到cache的时候用到了YYCache来做缓存, 然后里面提到了一个缓存算法LRU, 然后缓存算法常见的有LFU、LRU、ARC、FIFO、MRU(百度百科); 其中LRU称为 "最近最少使用算法",这里的增删主要使用链表来实现, 因为链表的增删都是O(1),(写到这里很慌, 希望没有说错, 不要被打脸)
这里有点模糊, 所以来重新复习一下数据结构以及算法, 都是实用的, 首先我找的资料呢是<<算法第四版>>, 这个是java实现的 然后参考了一下其他资料. 好的作为一个iOS开发人员, 我们首先来看一下链表的swift怎么实现
第一我们来实现一下链表
好了, 这里说几点, 第一这里的链表是使用类来实现的, 并不是用结构体,里面不能用存储属性, 而每一个节点我们都是这种存储属性, 这个用引用类型实现会比较好. 所以这里选择的是类, 而不是结构体.
第二步 我们用这个链表来实现一些基础的数据结构栈和队列和背包
大家注意到, 用链表可以很方便的实现栈和队列, 这里用数组也可以实现同样的功能,具体的区别在于对应的操作的效率,大家可以自己对比一下, 我还是比较推荐用链表实现, 因为主要是增删的操作对于链表是O(1), 对于数组是O(n)
在构建这几个基本的数据结构的时候呢, 用到了swift中关于迭代器和对列的相关协议.让链表可以像数组一样用forin循环进行操作, 并且提供了快捷的构建方法, 通过数组和字面量的两种形式
LRU算法: Least recently used,最近最少使用. 这个淘汰算法是指将最近访问过的数据插到最前面, 当超过限制之后从最后面删除数据.好吧, 现在我们来用链表来实现这个算法, 并且做一个能使在实际项目使用到的工具.
这里的算法实现也是通过包装链表的一些列方法来实现的, 这里需要讨论的问题是, 那么为什么不直接用链表来实现这些功能而是用一个协议来实现, 这就是为了更好封装性和安全性, 确保在这个算法里面没有冗余的方法和不可预测错误使用方式, 所以基于链表的这一系列的实现(包括上面的栈, 队列, 以及背包和RLU算法)都是通过包装链表已有的方法进行的实现, 同时这个协议的实现也提供了一种可能性, 就是如果有不同的想法, 比如我想用一个数组来实现一个栈, 也可以通过这个协议指定的规范来统一实现相应的方法就行了. 同时需要说明的是,协议不代表你实现了这个协议就一定是实现了这样的功能, 因为你可能实现了相同的方法但是逻辑并不是这么回事, 所以协议仅仅只是一个规范, 遵守规范还是需要人为把控.
这里要提一下就是要实现线程安全或者说是原子操作, 目前在iOS里面有来之pthread的锁(自旋锁, 互斥锁),以及GCD的信号量, barrier,以及iOS10提出的unfair_lock等, 上面提到的都是比较典型的. 然后这里要提醒一下的是自旋锁和信号量在iOS平台都是不安全的方式.具体的大家可以搜索一下很容易就能明白(不愿意搜索的我简单提一下, 是由于优先级的问题造成了无法unlock). 综合很多资料比较性能之后选用的是互斥锁, 并且选用了一个比较优的封装方案(避免了闭包捕获带来的额外开销, 以及swift对于inline的优化)