以下笔记为jjyaoao本人制作,欢迎借鉴学习和提出相关建议,转载需要标明出处www.jjyaoao.space
3.列表
从向量到列表
没有前驱/后继的唯一节点称为首/末

从静态到动态

从秩到位置
寻秩访问到循位置访问

列表所需模板类
ListNode
接口

1 2 3 4 5 6 7 8 9 10 11 12 13 14
| using Rank = int; 0002 template <typename T> struct ListNode; 0003 template <typename T> using ListNodePosi = ListNode<T>*; 0004 template <typename T> struct ListNode { 0005 0006 T data; ListNodePosi<T> pred; ListNodePosi<T> succ; 0007 0008 ListNode() {} 0009 ListNode ( T e, ListNodePosi<T> p = NULL, ListNodePosi<T> s = NULL ) 0010 : data ( e ), pred ( p ), succ ( s ) {} 0011 0012 ListNodePosi<T> insertAsPred ( T const& e ); 0013 ListNodePosi<T> insertAsSucc ( T const& e ); 0014 };
|
List
接口

宏观结构
header 和 trailer 是不可见的,可他们的作用非常巨大!
头与尾是与生俱来的,而且并不保证可以相同
而first和last并不见得不相同,甚至不能保证他们存在,但对外而言,first和last是可见的

初始化
1 2 3 4 5 6 7
| template <typename T> void List<T>::init() { 0002 header = new ListNode<T>; 0003 trailer = new ListNode<T>; 0004 header->succ = trailer; header->pred = NULL; 0005 trailer->pred = header; trailer->succ = NULL; 0006 _size = 0; 0007 }
|
插入与构造
前驱插入
即便是第一个节点和最后一个节点,我们说他仍然是正确的,因为有哨兵头尾的存在!

复制(构造)

删除与析构
删除
可以说P与原来的系统,在拓扑关系上脱离开了
微创手术型 O(1)

析构

查找
如果一串列表里有多个同样的,并且是查找的对象,则将会首先停止与最靠后的那个
为什么我们把n放在p的前端呢?(find传入参数)
因为这样我们很好理解,是在p的n个前驱中寻找
换而言之我们完全可以重载另一个接口find(e,p,n)

去重
r在任何时候其实就等于整个前缀(p)的长度
为什么删除q而不删除p呢
对于p而言,先删除q是一个更安全的方法(不改变目前遍历所达到的位置

1 2 3 4 5 6 7 8
| template <typename T> int List<T>::deduplicate() { 0002 int oldSize = _size; ListNodePosi<T> p = first(); 0003 for ( Rank r = 0; p != trailer; p = p->succ ) 0004 if ( ListNodePosi<T> q = find(p->data, r, p) ) 0005 remove(q); 0006 else r++; 0007 return oldSize - _size; 0008 }
|
实现(可忽略)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
| #include "listNode.h" 0002 0003 template <typename T> class List { 0004 0005 private: 0006 int _size; ListNodePosi<T> header; ListNodePosi<T> trailer; 0007 0008 protected: 0009 void init(); 0010 int clear(); 0011 void copyNodes ( ListNodePosi<T>, int ); 0012 ListNodePosi<T> merge ( ListNodePosi<T>, int, List<T> &, ListNodePosi<T>, int ); 0013 void mergeSort ( ListNodePosi<T> &, int ); 0014 void selectionSort ( ListNodePosi<T>, int ); 0015 void insertionSort ( ListNodePosi<T>, int ); 0016 void radixSort(ListNodePosi<T>, int); 0017 0018 public: 0019 0020 List() { init(); } 0021 List ( List<T> const& L ); 0022 List ( List<T> const& L, Rank r, int n ); 0023 List ( ListNodePosi<T> p, int n ); 0024 0025 ~List(); 0026 0027 Rank size() const { return _size; } 0028 bool empty() const { return _size <= 0; } 0029 T& operator[] ( Rank r ) const; 0030 ListNodePosi<T> first() const { return header->succ; } 0031 ListNodePosi<T> last() const { return trailer->pred; } 0032 bool valid ( ListNodePosi<T> p ) 0033 { return p && ( trailer != p ) && ( header != p ); } 0034 ListNodePosi<T> find ( T const& e ) const 0035 { return find ( e, _size, trailer ); } 0036 ListNodePosi<T> find ( T const& e, int n, ListNodePosi<T> p ) const; 0037 ListNodePosi<T> search ( T const& e ) const 0038 { return search ( e, _size, trailer ); } 0039 ListNodePosi<T> search ( T const& e, int n, ListNodePosi<T> p ) const; 0040 ListNodePosi<T> selectMax ( ListNodePosi<T> p, int n ); 0041 ListNodePosi<T> selectMax() { return selectMax ( header->succ, _size ); } 0042 0043 ListNodePosi<T> insertAsFirst ( T const& e ); 0044 ListNodePosi<T> insertAsLast ( T const& e ); 0045 ListNodePosi<T> insert ( ListNodePosi<T> p, T const& e ); 0046 ListNodePosi<T> insert ( T const& e, ListNodePosi<T> p ); 0047 T remove ( ListNodePosi<T> p ); 0048 void merge ( List<T> & L ) { merge ( header->succ, _size, L, L.header->succ, L._size ); } 0049 void sort ( ListNodePosi<T> p, int n ); 0050 void sort() { sort ( first(), _size ); } 0051 int deduplicate(); 0052 int uniquify(); 0053 void reverse(); 0054 0055 void traverse ( void (* ) ( T& ) ); 0056 template <typename VST> 0057 void traverse ( VST& ); 0058 };
|
有序列表
唯一化
构思

处理

1 2 3 4 5 6 7 8 9
| template <typename T> int List<T>::uniquify() { 0002 if ( _size < 2 ) return 0; 0003 int oldSize = _size; 0004 ListNodePosi<T> p = first(); ListNodePosi<T> q; 0005 while ( trailer != ( q = p->succ ) ) 0006 if ( p->data != q->data ) p = q; 0007 else remove ( q ); 0008 return oldSize - _size; 0009 }
|
查找

1 2 3 4 5 6 7 8
| template <typename T> 0002 ListNodePosi<T> List<T>::search ( T const& e, int n, ListNodePosi<T> p ) const { 0003 0004 do { 0005 p = p->pred; n--; 0006 } while ( ( -1 < n ) && ( e < p->data ) ); 0007 return p; 0008 }
|
列表-选择排序
构思

实例

selectionSort

1 2 3 4 5 6 7 8 9 10
| template <typename T> 0002 void List<T>::selectionSort ( ListNodePosi<T> p, int n ) { 0003 ListNodePosi<T> head = p->pred, tail = p; 0004 for ( int i = 0; i < n; i++ ) tail = tail->succ; 0005 while ( 1 < n ) { 0006 ListNodePosi<T> max = selectMax ( head->succ, n ); 0007 insert ( remove ( max ), tail ); 0008 tail = tail->pred; n--; 0009 } 0010 }
|
selectMax

1 2 3 4 5 6 7 8
| template <typename T> 0002 ListNodePosi<T> List<T>::selectMax ( ListNodePosi<T> p, int n ) { 0003 ListNodePosi<T> max = p; 0004 for ( ListNodePosi<T> cur = p; 1 < n; n-- ) 0005 if ( !lt ( ( cur = cur->succ )->data, max->data ) ) 0006 max = cur; 0007 return max; 0008 }
|
insertB
详情参考前驱插入部分
1 2 3 4 5 6 7 8 9 10 11
| template <typename T> ListNodePosi<T> List<T>::insertAsFirst ( T const& e ) 0002 { _size++; return header->insertAsSucc ( e ); } 0003 0004 template <typename T> ListNodePosi<T> List<T>::insertAsLast ( T const& e ) 0005 { _size++; return trailer->insertAsPred ( e ); } 0006 0007 template <typename T> ListNodePosi<T> List<T>::insert ( ListNodePosi<T> p, T const& e ) 0008 { _size++; return p->insertAsSucc ( e ); } 0009 0010 template <typename T> ListNodePosi<T> List<T>::insert ( T const& e, ListNodePosi<T> p ) 0011 { _size++; return p->insertAsPred ( e ); }
|
性能分析

列表-插入排序

构思

与选择排序区别
- 插入排序有序部分是前部分,选择排序有序部分是后部分
- 选择排序无序部分必然小于有序部分,插入排序并没有类似的规定,后面所选取的数字和此前所选取的没有任何关系
实例
减而治之,此消彼减

实现
insertA到选择排序的insertB里找(B:before A:after)

search
1 2 3 4 5 6 7 8
| template <typename T> 0002 ListNodePosi<T> List<T>::search ( T const& e, int n, ListNodePosi<T> p ) const { 0003 0004 do { 0005 p = p->pred; n--; 0006 } while ( ( -1 < n ) && ( e < p->data ) ); 0007 return p; 0008 }
|
remove
1 2 3 4 5 6
| template <typename T> T List<T>::remove ( ListNodePosi<T> p ) { 0002 T e = p->data; 0003 p->pred->succ = p->succ; p->succ->pred = p->pred; 0004 delete p; _size--; 0005 return e; 0006 }
|
性能分析

平均性能
运用数学期望的线性率,一组随机变量总和的期望(平均值)等于他们各自期望的总和
无论他们是互不相关的还是相关的,这都是正确的
