双向链表…

相对于前一篇的Vector,List就稍微复杂了一些。

它的好处是每次插入或删除一个元素,就配置或者释放一个空间。

List对空间的运用十分精准,不会有一丝一毫的浪费。

对于已知位置的元素的插入与删除,List永远是常数时间O(1)

 

List的结点:

List的结点的结构如下:很明显这是一个双向链表…

 

List的迭代器:

List的迭代器与Vector还是不一样的,因为List结点在空间中并不是连续存放的,所以必须重新设计一个迭代器。

需要完成的功能是:正确的 递增(指向下一个节点)、递减(指向上一个节点)、取值(取节点数据值)、成员存取(取节点的成员)等操作。

同时因为List的设计是一个双向链表,所以提供的是Bidirectional Iterators(双向迭代器)

List的一个重要性质是,插入操作(insert)和接合操作(splice)都不会造成原有的list的迭代器失效,删除操作(erase)也只有被删除的迭代器失效,对其他迭代器无影响。

 

List的数据结构:

List不仅是一个双向链表,而且还是一个环状双向链表,它只需要一个指针,便可以完整表现整个链表。

 

如果让指针node指向刻意置于尾端的一个空白节点,node便能符合STL对于“前闭后开”区间的要求,成为last迭代器。

如图所示:

STL-List

如此一来,以下几个函数便都可以轻易实现:

 

List的构造与内存管理:

construct, push_back, insert

4list-test.cpp :

List缺省使用alloc作为空间配置器,并据此另外定义了一个list_node_allocator,为的是更方便地以节点大小为配置单位:

当我们调用 push_back时,此函数内部调用insert函数:

Insert函数是一个重载函数,有多种形式,最简单的一种如下:

配置并构造一个结点,然后在尾端进行指针操作,将节点插入。

 

List的元素操作:

push_front, push_back, erase, pop_front, pop_back, clear, remove, unique, merge, reverse, sort

List提供的元素操作很多,在此仅选侯捷大神书上写的记载。

 

以上这些是写在class内的,默认内联

然后还有一些稍复杂的定义在class外:

同时,List内部还提供一个迁移操作(transfer),它的作用是,将某连续范围内的元素迁移到某个特定位置之前。

技术上就是简单的结点指针移动,但是它为后面的 splice,sort,merge奠定良好的基础。

下面是transfer的源代码:

以下是示意图:

List-transfer

transfer并非公开的接口,list公开的接合操作实际上是splice。

可以在之前的 4list-test.cpp 程序最后再执行:

 

为了适应不同的情况,splice有许多不的版本:

 

以下是merge(), reverse(), sort() 的源代码,有了transfer,这些操作都很简单。

Merge函数,要求两个list都已经提前排序好:

 

Reverse()函数,将*this的内容逆向重置:

做法是每次把未移动部分的首元素的后一个元素移动到begin()前面。

例如: (1 2 3) -> 2 (1 3) -> 3 2 (1)  完毕!

(1 2 3 4)->2 (1 3 4) -> 3 2 (1 4) -> 4 3 2 (1) 完毕!

 

最后要注意的是,list不能使用STL自带的Sort算法,只能使用自己的sort()

因为STL的 sort算法只支持 RandomAccessIterator(随机存取迭代器)

本函数采用的是quicksort的方式。

说实话,这个排序我也还没看懂…我们慢慢来好吗?

…2016.7.17记于此。

7.18 后记:今天中午抽空模拟了一遍整个排序流程…

结果发现被坑!根本不是quick sort好么…用的归并的思想。

List-sort

计算了一半其实就可以看出来了…这是归并排序的思想。

给了64个counter,所以能够排序的数量是2^64-1个数字,是很大的了。

时间复杂度呢,是n*log(n),这个不解释,归并都是这么快。

空间复杂度呢,是64个list(counter)和一个list(carry) 和一个fill,一个i…开销是很小的。

 

【STL】List
Tagged on:
0 0 投票数
Article Rating
订阅评论
提醒

0 评论
内联反馈
查看所有评论