列表也是一组元素的集合。
特点是:增删快,查找慢。
列表和向量的区别是向量的元素都是在内存中连续存储,列表则不能保证元素在内存中是否连续存储。
元素节点
ListNode.h
typedef int Rank; #define ListNodePosi(T) ListNode<T>* //列表节点位置 template <typename T> struct ListNode { T data; ListNodePosi(T) pred; ListNodePosi(T) succ; //构造函数 ListNode() {} ListNode(T e,ListNodePosi(T) p = NULL,ListNodePosi(T) s = NULL):data(e),pred(p),succ(s){} //操作接口 ListNodePosi(T) insertAsPred(T const& e); ListNodePosi(T) insertAsSucc(T const& e); };
ListNode.cpp
template <typename T> ListNodePosi(T) ListNode<T>::insertAsPred(T const&e){ ListNodePosi(T) x = new ListNode(e, pred, this); pred -> succ = x; pred = x; return x; } template <typename T> ListNodePosi(T) ListNode<T>::insertAsSucc(T const&e){ ListNodePosi(T) x = new ListNode(e, this, succ); succ -> pred = x; succ = x; return x; }
列表ADT List.h
#include "ListNode.hpp" #include <iostream> template <typename T> class List{ private: int _size; ListNodePosi(T) header; ListNodePosi(T) trailer; protected: void init(); //列表创建时的初始化 int clear(); //清楚所有节点 void copyNodes(ListNodePosi(T),int); //复制列表中自位置p起的n项 void merge(ListNodePosi(T)&, int, List<T>&, ListNodePosi(T), int); //归并 void mergeSort(ListNodePosi(T)&,int); void selectionSort(ListNodePosi(T),int); void insertionSort(ListNodePosi(T),int); void reverse(); public: List() { init(); } List(List<T> const& L); List(List<T> const& L,Rank r,int n); List(ListNodePosi(T) p,int n); ~List(); //只读访问接口 Rank size() const { return _size; } bool empty() const { return _size <= 0; } T& operator[](Rank r) const; ListNodePosi(T) first() const { //首节点位置 return header -> succ; } ListNodePosi(T) last() const { //末节点位置 return trailer -> pred; } bool valid(ListNodePosi(T) p) { return p && (trailer != p) && (header != p); } int disordered() const; ListNodePosi(T) find(T const& e)const { return find(e, _size, trailer); } ListNodePosi(T) find(T const&e,int n,ListNodePosi(T) p) const; ListNodePosi(T) search(T const& e) const { return search(e, _size, trailer); } ListNodePosi(T) search(T const& e,int n,ListNodePosi(T) p) const; ListNodePosi(T) selectMax(ListNodePosi(T) p,int n); ListNodePosi(T) selectMax() { return selectMax(header->succ, _size); } //可写访问接口 ListNodePosi(T) insertAsFirst(T const& e); ListNodePosi(T) insertAsLast(T const& e); ListNodePosi(T) insertA(ListNodePosi(T) p, T const& e); ListNodePosi(T) insertB(ListNodePosi(T) p,T const& e); T remove(ListNodePosi(T) p); void merge(List<T>& L){ merge(first(), size(), L, L.first(), L._size); } void sort(ListNodePosi(T) p,int n); void sort() { sort(first(), _size); } int deduplicate(); int uniquify(); // void reverse(); //遍历 void traverse(void (*)(T&)); template <typename VST> void traverse(VST&); };
List.cpp
#include <algorithm> template <typename T> void List<T>::init() { header = new ListNode<T>; trailer = new ListNode<T>; header -> succ = trailer; header -> pred = NULL; trailer -> pred = header; trailer -> succ = NULL; _size = 0; } //重载下标运算符 template <typename T> T& List<T>::operator[](Rank r)const { //assert: 0<=r<size ListNodePosi(T) p = first(); while (0 < r--) { p = p -> succ; } return p -> data; } //在无序列表内节点p的n个前驱中,找到等于e的最后者 template <typename T> ListNodePosi(T) List<T>::find(const T &e, int n, ListNodePosi(T) p)const { while (0 < n--) { if (e == (p = p -> pred) -> data) { return p; } } return NULL; } template <typename T> ListNodePosi(T) List<T>::insertAsFirst(T const&e) { _size++; return header -> insertAsSucc(e); } template <typename T> ListNodePosi(T) List<T>::insertAsLast(T const&e){ _size++; return trailer -> insertAsPred(e); } template <typename T> ListNodePosi(T) List<T>::insertA(ListNode<T> *p, T const&e){ _size++; return p -> insertAsSucc(e); } template <typename T> ListNodePosi(T) List<T>::insertB(ListNode<T> *p, T const&e){ _size++; return p -> insertAsPred(e); } //列表内部方法:复制列表中自位置p起的n项 template <typename T> void List<T>::copyNodes(ListNodePosi(T) p, int n){ init(); while (n--) { insertAsLast(p->data); p = p -> succ; } } template <typename T> List<T>::List(ListNodePosi(T) p,int n) { copyNodes(p, n); } template <typename T> List<T>::List(List<T> const& L) { copyNodes(L.first(), L._size); } //复制L中自第r项起的n项 (assert: r+n <= L._size) template <typename T> List<T>::List(List<T> const& L,Rank r,int n){ copyNodes(L[r], n); } //在列表中删除指定节点p template <typename T> T List<T>::remove(ListNodePosi(T) p){ T e = p -> data; p -> pred -> succ = p -> succ; p -> succ -> pred = p -> pred; delete p; _size--; return e; } template <typename T> int List<T>::clear() { int oldSize = _size; while (0 < _size) { remove(header -> succ); } return oldSize; } template <typename T> List<T>::~List(){ clear(); delete header; delete trailer; } template <typename T> int List<T>::deduplicate() { if (_size < 2) { //平凡列表自然无重复 return 0; } int oldSize = _size; ListNodePosi(T) p = header; Rank r = 0; while (trailer != (p = p ->succ)) { ListNodePosi(T) q = find(p -> data, r, p); q ? remove(q) : r++; }//assert:循环过程中的任意时刻,p的所有前驱互不相同 return oldSize - _size; } template <typename T> void List<T>::traverse(void (*visit)(T &)) { for (ListNodePosi(T) p = header->succ; p != trailer; p = p->succ) { visit(p -> data); } } template <typename T> template <typename VST> void List<T>::traverse(VST &visit) { for (ListNodePosi(T) p = header->succ; p != trailer; p = p->succ) { visit(p -> data); } } #pragma mark - 有序列表 //成批删除重复元素,效率更高 template <typename T> int List<T>::uniquify() { if (_size < 2) { return 0; } int oldSize = _size; ListNodePosi(T) p = first(); ListNodePosi(T) q; while (trailer != (q = p -> succ)) { if (p -> data != q -> data) { p = q; }else{ remove(q); } } return oldSize - _size; } //在有序列表内节点p的n个前驱中,找到不大于e的最后者 template <typename T> ListNodePosi(T) List<T>::search(T const&e, int n, ListNodePosi(T) p) const{ //assert: 0 <= n <= rank(p) < _size while (0 <= n--) { if (( (p = p -> pred)->data ) <= e) { break; } } return p; } #pragma mark - 排序 template <typename T> void List<T>::sort(ListNodePosi(T) p, int n){ switch (rand() % 3) { case 1: insertionSort(p, n);break; case 2: selectionSort(p, n);break; default: mergeSort(p, n);break; } } //插入排序 template <typename T> void List<T>::insertionSort(ListNodePosi(T) p, int n){ for (int r = 0; r < n; r++) { insertA(search(p->data, r, p), p->data); p = p -> succ; remove(p->pred); } } //从起始于位置p的n个元素中选出最大者 template <typename T> ListNodePosi(T) List<T>::selectMax(ListNodePosi(T) p, int n){ ListNodePosi(T) max = p; for (ListNodePosi(T) cur = p; 1 < n; n--) { if (! lt( (cur=cur->succ)->data, max->data )) { max = cur; } } return max; } //选择排序,对起始于位置p的n个元素排序 template <typename T> void List<T>::selectionSort(ListNodePosi(T) p, int n){ //valid(p) && rank(p)+n<=size ListNodePosi(T) head = p -> pred; ListNodePosi(T) tail = p; for (int i = 0; i < n; i++) { //待排序区间为(head, tail) tail = tail -> succ; } while (1 < n) { //找出最大者(歧义时后者优先) ListNodePosi(T) max = selectMax(head -> succ, n); //将其移至无序区间末尾(作为有序区间新的首元素) insertB(tail, remove(max)); tail = tail -> pred; n--; } } //有序列表的归并:当前列表中自p起的n个元素,与列表L中自q起的m个元素归并 template <typename T> void List<T>::merge(ListNodePosi(T) &p,int n,List<T> &L,ListNodePosi(T) q,int m){ //注意:在归并排序之类的场合,有可能this==L && rank(p)+n = rank(q) //借助前驱(可能是header),以便返回前... ListNodePosi(T) pp = p -> pred; while (0 < m) { if ( (0 < n) && (p -> data <= q -> data)) { //p归入合并的列表,并替换为其直接后继 if (q == (p = p -> succ)) { break; } n--; }else{ //若p已超出右界或v(q) < v(p) insertB(p, L.remove( (q = q -> succ) -> pred)); m--; } } p = pp -> succ; } //列表的归并排序算法:对起始于位置p的n个元素排序 template <typename T> void List<T>::mergeSort(ListNodePosi(T) &p, int n){ if (n < 2) { return; } int m = n >> 1; //以中点为界,均分列表 ListNodePosi(T) q = p; for (int i=0; i < m; i++) { q = q -> succ; } //对前后子列表分别排序 mergeSort(p, m); mergeSort(q, n-m); merge(p, m, *this, q, n-m); //归并 }//注意:排序后,p依然指向归并后区间的(新)起点 template <typename T> void List<T>::reverse() { ListNodePosi(T) p = header; ListNodePosi(T) q = trailer; for (int i = 1; i < _size; i += 2) { std::swap( (p = p -> succ) -> data, (q = q -> pred) -> data); //交换对称节点的数据项 } }