首页 > 代码库 > 从deque到std::stack,std::queue,再到iOS 中NSArray(CFArray)

从deque到std::stack,std::queue,再到iOS 中NSArray(CFArray)

从deque到std::stack,std::queue,再到iOS 中NSArray(CFArray)

deque

deque双端队列,分段连续空间数据结构,由中控的map(与其说map,不如说是数组)控制,map中每个槽指向一个固定大小的缓冲(连续的线性空间)。 
deque的迭代器,关键的四个指针:

cur     //所指缓冲区中的现元素
first   //所指缓冲区中的头
last    //所指缓冲区中的尾
node    //指向中控的槽

技术分享

start指向中控第一个槽位的buffer中的第一个元素,finish指向中控最后一个槽位指向的buffer中的最后一个元素。 
每次新建deque时,创建中控map和nodes,根据初始的元素个数计算开始槽位nstart和nfinish。

map_pointer nstart = map + (map_size - num_nodes) / 2;
map_pointer nfinish = nstart + num_nodes - 1;

这样做的原因是双端push或pop时的平均性能最佳。

如图,如果需要push_back,刚好finish指向的buffer将满,会向map中finish后一个槽位新建一个buffer node;对应的push_front会向map中start前一个槽位新建一个buffer node;如果map不够空间,也还是要reallocate_map,重新分配map空间迁移已有数据,释放老数据。

std::stack,std::queue

  • stack是FILO的数据结构,只有一个出口,若以上述的deque实现,封住deque的头端开口,轻易就能实现stack,stack往往不被归为container,而被归为container adapter,源码十分简短,底层容器就是deque(当然也可以使用list:如stack<int, list >)
class Sequence = deque<T>
  • queue是FIFO的数据结构,封住back的出口和front的入口即可轻易实现,代码同stack,也被认为是container adapter。

NSArray(CF-1151.16源码中的CFArray)

iOS中为什么没有实现stack,queue这样的适配器?应该是CFArray底层也是类似双端队列这样的数据结构,可以轻易实现FILO或FIFO功能,就没必要再多此一举了。 
刚好在 CFArray.c 源码中定义了__CFArrayDeque,和各种deque相关操作的方法。

struct __CFArrayDeque {
    uintptr_t _leftIdx;
    uintptr_t _capacity;
    /* struct __CFArrayBucket buckets follow here */
};

但是苹果的NSArray真实实现谁也不知道,也可能是 环形队列,这样貌似性能更高,请看这篇文章; 
和其他容器的实现。

小结

关于iOS为什么不实现std::stack和std::queue,可能苹果觉得NSMutableArray完全可以通过deque的性质轻易的实现FILO或FIFO特性,再实现就是多此一举了吧。 
ps:CF源码我还没看完,继续啃吧。

参考

  • 《STL 源码剖析》
  • http://blog.ibireme.com/2014/02/17/cfarray/
  • https://github.com/ibireme/yy_music_base/tree/master/yy_music_base

从deque到std::stack,std::queue,再到iOS 中NSArray(CFArray)