双向链表

来源:互联网 发布:python截取中文字符串 编辑:程序博客网 时间:2024/06/05 14:50
/*protected:   void init()                                                                  列表创建时的初始化   int clear()                                                                  清除所有节点   void copyNodes ( nodePos(T), int )                                           复制列表中自位置p起的n项   void merge ( nodePos(T)&, int, List<T>&, ListNodePosi(T), int )              归并   void mergeSort ( nodePos(T)&, int )                                          对从p开始连续的n个节点归并排序   void selectionSort ( nodePos(T), int )                                       对从p开始连续的n个节点选择排序   void insertionSort ( nodePos(T), int )                                       对从p开始连续的n个节点插入排序public:构造函数   List()                                                                       默认   List ( List<T> const& L )                                                    整体复制列表L   List ( List<T> const& L, Rank r, int n )                                     复制列表L中自第r项起的n项   List ( nodePos(T) p, int n )                                                 复制列表中自位置p起的n项析构函数   ~List()                                                                      释放(包含头、尾哨兵在内的)所有节点只读访问接口   Rank size() const                                                            规模   bool empty() const                                                           判空   T& operator[] ( Rank r ) const                                               重载,支持循秩访问(效率低)   nodePos(T) first() const                                                     首节点位置   nodePos(T) last() const                                                      末节点位置   bool valid ( nodePos(T) p )                                                  判断位置p是否对外合法   int disordered() const                                                       判断列表是否已排序   nodePos(T) find ( T const& e ) const                                         无序列表查找   nodePos(T) find ( T const& e, int n, nodePos(T) p ) const                    无序区间查找   nodePos(T) search ( T const& e ) const                                       有序列表查找   nodePos(T) search ( T const& e, int n, nodePos(T) p ) const                  有序区间查找   nodePos(T) selectMax ( nodePos(T) p, int n )                                 在p及其n-1个后继中选出最大者   nodePos(T) selectMax()                                                       整体最大者可写访问接口   nodePos(T) insertAsFirst ( T const& e )                                      将e当作首节点插入   nodePos(T) insertAsLast ( T const& e )                                       将e当作末节点插入   nodePos(T) insertAfter ( nodePos(T) p, T const& e )                              将e当作p的后继插入   nodePos(T) insertBefore ( nodePos(T) p, T const& e )                              将e当作p的前驱插入   T remove ( ListNodePosi(T) p )                                               删除合法位置p处的节点,返回被删除节点   void merge ( List<T>& L )                                                    全列表归并   void sort ( nodePos(T) p, int n )                                            列表区间排序   void sort() 列表整体排序   int deduplicate() 无序去重   int uniquify() 有序去重   void reverse() 前后倒置遍历   void traverse ( void (* ) ( T& ) )                                           遍历,依次实施visit操作(函数指针,只读或局部性修改)   template <typename VST>   void traverse ( VST& )                                                       遍历,依次实施visit操作(函数对象,可全局性修改) */#include <cstdlib>#include <cmath>//列表节点位置#define nodePos(T) node<T>*//秩typedef int Rank;//less thantemplate <typename T>static bool lt ( T& a, T& b ) {    return a < b;}//列表节点template <typename T>struct node {    // 成员    T data;    nodePos(T) pred;    nodePos(T) succ;    // 构造函数    //针对header和trailer的构造    node() {}    //默认构造器    node ( T e, nodePos(T) p = NULL, nodePos(T) s = NULL )            : data ( e ), pred ( p ), succ ( s ) {}    // 操作接口    nodePos(T) insertAsPred ( T const& e ){        nodePos(T) x = new node ( e, pred, this );        pred->succ = x; pred = x;        return x;    }    nodePos(T) insertAsSucc ( T const& e ){        nodePos(T) x = new node ( e, this, succ );        succ->pred = x; succ = x;        return x;    }};//列表template <typename T>class list {private:    //规模    int _size;    //头哨兵    nodePos(T) header;    //尾哨兵    nodePos(T) trailer;protected:    //列表初始化,在创建列表对象时统一调用    void init(){        //创建头哨兵节点        header = new node<T>        //创建尾哨兵节点        trailer = new node<T>        //连接指针        header->succ = trailer;        header->pred = NULL;        trailer->pred = header;        trailer->succ = NULL;        //记录规模        _size = 0;    }    //清空列表    int clear(){        int oldSize = _size;        //反复删除首节点,直至列表变空        while ( 0 < _size )            remove ( header->succ );        return oldSize;    }    //p合法,且至少有n-1个真后继节点    void copyNodes ( nodePos(T) p, int n){        //创建头、尾哨兵节点并做初始化        init();        //将起自p的n项依次作为末节点插入        while ( n-- ) {            insertAsLast ( p->data );            p = p->succ;        }    }    void merge ( nodePos(T)& p, int n, list<T>& L, nodePos(T) q, int m){// assert:  this.valid(p) && rank(p) + n <= size && this.sorted(p, n)//          L.valid(q) && rank(q) + m <= L._size && L.sorted(q, m)// 注意:在归并排序之类的场合,有可能 this == L && rank(p) + n = rank(q)        nodePos(T) pp = p->pred; //借助前驱(可能是header),以便返回前 ...        while ( 0 < m ) //在q尚未移出区间之前            if ( ( 0 < n ) && ( p->data <= q->data ) ) //若p仍在区间内且v(p) <= v(q),则            { if ( q == ( p = p->succ ) ) break; n--; } //p归入合并的列表,并替换为其直接后继            else //若p已超出右界或v(q) < v(p),则            { insertB(p, L.remove((q = q->succ)->pred)); m--; } //将q转移至p之前        p = pp->succ; //确定归并后区间的(新)起点    }    void mergeSort ( nodePos(T)& p, int n){        //valid(p) && rank(p) + n <= size        //若待排序范围已足够小,则直接返回;否则...        if ( n < 2 )            return;        //以中点为界        int m = n >> 1;        nodePos(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依然指向归并后区间的(新)起点    void selectionSort ( nodePos(T) p, int n){        //valid(p) && rank(p) + n <= size        nodePos(T) head = p->pred;        nodePos(T) tail = p;        //待排序区间为(head, tail)        for ( int i = 0; i < n; i++ )            tail = tail->succ;        //在至少还剩两个节点之前,在待排序区间内        while ( 1 < n ) {            //找出最大者(歧义时后者优先)            nodePos(T) max = selectMax ( head->succ, n );            //将其移至无序区间末尾(作为有序区间新的首元素)            insertB(tail, remove(max));            tail = tail->pred;            n--;        }    }    void insertionSort ( nodePos(T) p, int n){        //valid(p) && rank(p) + n <= size        //逐一为各节点        for ( int r = 0; r < n; r++ ) {            //查找适当的位置并插入            insertA(search(p->data, r, p), p->data);            //转向下一节点            p = p->succ;            remove ( p->pred );        }    }public:    // 构造函数    //默认    list() {        init();    }    list ( list<T> const& L ){        copyNodes ( L.first(), L._size );    }    list ( list<T> const& L, Rank r, int n ){        copyNodes ( L[r], n );    }    list ( nodePos(T) p, int n ){        copyNodes ( p, n );    }    // 析构函数    ~list(){        clear();        delete header;        delete trailer;    }    // 只读访问接口    //规模    Rank size() const {        return _size;    }    //判空    bool empty() const {        return _size <= 0;    }    T& operator[] ( Rank r ) const{ //assert: 0 <= r < size        //从首节点出发        nodePos(T) p = first();        //顺数第r个节点即是        while ( 0 < r-- ) p = p->succ;        //目标节点,返回其中所存元素        return p->data;    }    //首节点位置    nodePos(T) first() const {        return header->succ;    }    //末节点位置    nodePos(T) last() const {        return trailer->pred;    }    //判断位置p是否对外合法    bool valid ( nodePos(T) p ) {        //将头、尾节点等同于NULL        return p && ( trailer != p ) && ( header != p );    }    //统计逆序相邻元素对的总数    int disordered() const{        int n = 0; node<T>* p = first();        for ( int i = 0; i < _size - 1; p = p->succ, i++ )            if ( p->data > p->succ->data )                n++;        return n;    }    //无序列表查找    nodePos(T) find ( T const& e ) const {        return find ( e, _size, trailer );    }    nodePos(T) find ( T const& e, int n, nodePos(T) p ) const{        //(0 <= n <= rank(p) < _size)对于p的最近的n个前驱,从右向左        //逐个比对,直至命中或范围越界        while ( 0 < n-- )            if ( e == ( p = p->pred )->data )                return p;        //p越出左边界意味着区间内不含e,查找失败        //失败时,返回NULL        return NULL;    }    //有序列表查找    nodePos(T) search ( T const& e ) const{        return search ( e, _size, trailer );    }    nodePos(T) search ( T const& e, int n, nodePos(T) p ) const{        // assert: 0 <= n <= rank(p) < _size        //对于p的最近的n个前驱,从右向左逐个比较        while ( 0 <= n-- )            //直至命中、数值越界或范围越界            if ( ( ( p = p->pred )->data ) <= e )                break;        // assert: 至此位置p必符合输出语义约定——尽管此前最后一次关键码比较可能没有意义(等效于与-inf比较)        //返回查找终止的位置        return p;    } //失败时,返回区间左边界的前驱(可能是header)——调用者可通过valid()判断成功与否    nodePos(T) selectMax ( nodePos(T) p, int n ){        //最大者暂定为首节点p        nodePos(T) max = p;        //从首节点p出发,将后续节点逐一与max比较        for ( nodePos(T) cur = p; 1 < n; n-- )            //若当前元素不小于max,则            if ( !lt ( ( cur = cur->succ )->data, max->data ) )                //更新最大元素位置记录                max = cur;        //返回最大节点位置        return max;    }    //整体最大者    nodePos(T) selectMax() {        return selectMax ( header->succ, _size );    }    // 可写访问接口    nodePos(T) insertAsFirst ( T const& e ){        _size++;        return header->insertAsSucc ( e );    } //e当作首节点插入    nodePos(T) insertAsLast ( T const& e ){        _size++;        return trailer->insertAsPred ( e );    } //e当作末节点插入    nodePos(T) insertA ( nodePos(T) p, T const& e ){        _size++;        return p->insertAsSucc ( e );    } //e当作p的后继插入(After)    //e当作p的前驱插入(Before)    nodePos(T) insertB ( nodePos(T) p, T const& e ){        _size++;        return p->insertAsPred ( e );    }    //删除合法节点p,返回其数值    T remove ( nodePos(T) p ){        //备份待删除节点的数值(假定T类型可直接赋值)        T e = p->data;        //后继、前驱        p->pred->succ = p->succ;        p->succ->pred = p->pred;        //释放节点,更新规模        delete p;        _size--;        //返回备份的数值        return e;    }    //全列表归并    void merge ( list<T>& L ) {        merge ( this->header->succ, this->_size, L, L.first(), L._size );    }    //列表区间排序    void sort ( nodePos(T) p, int n ){        //随机选取排序算法。可根据具体问题的特点灵活选取或扩充        switch ( rand() % 3 ) {            //插入排序            case 1:                insertionSort ( p, n );                break;            //选择排序            case 2:                selectionSort ( p, n );                break;            //归并排序            default:                mergeSort ( p, n );                break;        }    }    //列表整体排序    void sort() {        sort ( first(), _size );    }    //剔除无序列表中的重复节点    int deduplicate(){        //平凡列表自然无重复        if ( _size < 2 )            return 0;        //记录原规模        int oldSize = _size;        //p从首节点开始        nodePos(T) p = header;        Rank r = 0;        //依次直到末节点        while ( trailer != ( p = p->succ ) ) {            //在p的r个(真)前驱中查找雷同者            nodePos(T) q = find ( p->data, r, p );            //若的确存在,则删除之;否则秩加一            q ? remove ( q ) : r++;        } //assert: 循环过程中的任意时刻,p的所有前驱互不相同        //列表规模变化量,即被删除元素总数        return oldSize - _size;    }    //成批剔除重复元素,效率更高    int uniquify(){        //平凡列表自然无重复        if ( _size < 2 )            return 0;        //记录原规模        int oldSize = _size;        //p为各区段起点,q为其后继        nodePos(T) p = first(); nodePos(T) q;        //反复考查紧邻的节点对(p, q)        while ( trailer != ( q = p->succ ) )            //若互异,则转向下一区段            if ( p->data != q->data ) p = q;                //否则(雷同),删除后者            else remove ( q );        //列表规模变化量,即被删除元素总数        return oldSize - _size;    }    //前后倒置    void reverse(){        //头、尾节点        nodePos(T) p = header;        nodePos(T) q = trailer;        //(从首、末节点开始)由外而内,逐对地交换对称节点的数据项        for ( int i = 1; i < _size; i += 2 )            std::swap( ( p = p->succ )->data, ( q = q->pred )->data );    }    // 遍历    void traverse ( void (*visit ) ( T& ) ){        //遍历,依次实施visit操作(函数指针,只读或局部性修改)        for ( nodePos(T) p = header->succ; p != trailer; p = p->succ )            visit ( p->data );    }    template <typename VST> //操作器    //遍历,依次实施visit操作(函数对象,可全局性修改)    void traverse ( VST& visit ){        for ( nodePos(T) p = header->succ; p != trailer; p = p->succ )            visit ( p->data );    }};
原创粉丝点击