列表也是一组元素的集合。

特点是:增删快,查找慢。

列表和向量的区别是向量的元素都是在内存中连续存储,列表则不能保证元素在内存中是否连续存储。

元素节点

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); //交换对称节点的数据项
    }
    
}

 

posted on 2018-11-11 21:39  迷心迷  阅读(216)  评论(0编辑  收藏  举报