从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 */ };
小结
关于iOS为什么不实现std::stack和std::queue,可能苹果觉得NSMutableArray完全可以通过deque的性质轻易的实现FILO或FIFO特性,再实现就是多此一举了吧。
ps:CF源码我还没看完,继续啃吧。