List的实现

来源:互联网 发布:软件实施工程师前景 编辑:程序博客网 时间:2024/05/21 10:54

本节我们提供list类模板的实现,在考虑设计时,我们需要提供如下4个类:

  1. List类本身,它包含连接到表两端的链、表的大小,以及一些方法。
  2. Node类,他很可能是一个私有的内嵌类。一个节点包含数据和指向前后两个节点的两个指针,以及一些适当的构造函数。
  3. const_iterator类,它抽象了为位置的概念,而且是一个公有的内嵌类。该const_iterator类储存一个指向“当前”节点的指针,并提供基本迭代器操作的实现,如=、==、!=、++等,均以重载运算符的形式出现。
  4. iterator类,类似3,继承自3。

为了算法的通用性,我们引入两个附加节点——头节点和尾节点。
带有头节点和尾节点的双向链表
图. 带有头节点和尾节点的双向链表

#ifndef LIST_H#define LIST_Htemplate <typename Object>class List{private:    struct Node{        Object data;        Node *prev;        Node *next;        Node( const Object& d = Object{ }, Node *p = nullptr,                                                                  Node *n = nullptr)            : data(d), prev(p), next(n) { }        Node(Object && d, Node *p = nullptr, Node *n = nullptr )            : data(d), prev(p), next(n) { }    };public:    class const_iterator{    public:        const_iterator( ): current( nullptr )            { }        const Object & operator* ( ) const            { return retrive( ); }        const_iterator operator++ ( )            {                current = current->next;                return *this;            }        const_iterator operator ++( int )        {            const_iterator old = *this;            ++(*this);            return old;        }        bool operator ==( const const_iterator & rhs ) const        { return current == rhs.current; }        bool operator != ( const const_iterator & rhs ) const        { return !( *this == rhs ); }    protected:        Node *current;        Object& retrive( ) const            { return current->data; }        const_iterator( Node *p ): current(p)            { }        friend class List<Object>;    };    class iterator: public const_iterator{    public:        iterator( )        { }        Object & operator *( )        { return const_iterator::retrive(); }        const Object & operator *( ) const        { return const_iterator::operator *( ); }        iterator & operator ++( )        {            this->current = this->current->next;            return *this;        }        iterator operator ++( int )        {            iterator old = *this;            ++(*this);            return old;        }        iterator & operator --( )        {            this->current = this->current->prev;            return *this;        }    protected:        iterator ( Node *p ) : const_iterator(p)        { }        friend class List<Object>;    };public:    List( )    {        init( );    }    List( const List& rhs )    {        init();        for(auto &x : rhs)            push_back(x);    }    ~List( )    {        clear( );    }    List& operator= ( const List& rhs )    {        List copy = rhs;        std::swap( *this, copy );        return *this;    }    List( List&& rhs )        : theSize( rhs.theSize ), head( rhs.head ), tail( rhs.tail )    {        rhs.theSize = 0;        rhs.head = nullptr;        rhs.tail = nullptr;    }    List& operator = ( List&& rhs )    {        std::swap( theSize, rhs.theSize );        std::swap( head, rhs.head );        std::swap( tail, rhs.tail );        return *this;    }    iterator begin( )        { return {head->next}; }    const_iterator cbegin() const        {return {head->next}; }    iterator end()        { return {tail}; }    const_iterator cend()        {return {tail};}    int size( ) const        {return theSize;}    bool empty( ) const        {return size( )==0;}    void clear( )    {        while(!empty())            pop_front( );    }    Object& front( )        {return *begin();}    const Object& front( ) const        //区分        {return *cbegin();}    Object& back()        {return *--end();}    const Object& back() const        {return *--cend();}    void push_front( const Object& x )        {insert( begin(), x );}    void push_front( Object&& x )        {insert ( begin(), std::move(x));}    void push_back( const Object& x )        { insert( end(), x);}    void push_back( Object&& x )        {insert(end(), std::move(x)); }    void pop_front( )        {erase(begin()); }    void pop_back( )        {erase (--end()); }    //  在itr前插入x    iterator insert( iterator itr, const Object& x )    {        Node *p = itr.current;        theSize++;        return { p->prev = p->prev->next = new Node{ x, p->prev, p } };    }    iterator insert( iterator itr, Object&& x )    {        Node *p = itr.current;        theSize++;        return { p->prev = p->prev->next = new Node{ std::move(x), p->prev, p} };    }    iterator erase( iterator itr )    {        Node *p = itr.current;        iterator retVal{ p->next };        p->prev->next = p->next;        p->next->prev = p->prev;        delete p;        theSize--;        return retVal;    }    iterator erase( iterator from, iterator to )    {        for(iterator itr=from; itr!=to; )            itr = erase(itr);        return to;    }private:    int theSize;    Node *head;    Node *tail;    void init( )    {        theSize = 0;        head = new Node;        tail = new Node;        head->next = tail;        tail->prev = head;    }};#endif // LIST_H
#include <iostream>#include "list.h"using namespace std;int main(int argc, char *argv[]){    List<int> lst;    for(int i=0; i<10; i++)        lst.push_back(i);    for(auto itr=lst.begin(); itr!=lst.end(); ++itr)        cout<<*itr<<" ";    cout<<endl;    lst.erase(++lst.begin(), --lst.end());    for(auto itr=lst.begin(); itr!=lst.end(); ++itr)        cout<<*itr<<" ";    return 0;}
  • 插入新节点:

假设要在pp.prev直接插入值为x的新节点,节点指针的赋值可描述为:

Node *newNode = new Node{ x, p.prev, p };p->prev->next = newNode;p.prev = newNode;

可将后上面的过程合并为:

p->prev = p->prev->next = new Node{ x, p->prev, p };
  • 删除节点:
p->prev->next = p->next;p->next->prev = p->prev;delete p;
  • erase例程
    erase返回一个代表被删除元素的后面的项的iterator, 必须更新theSize,在erase的第二个版本中直接使用iterator调用第一个版本的erase。注意!我们不能在其for循环中直接使用itr++并忽略erase的返回值。itr的值在调用erase后马上就过时了,这就是erase返回一个iterator的原因。
    iterator erase( iterator itr )    {        Node *p = itr.current;        iterator retVal{ p->next };        p->prev->next = p->next;        p->next->prev = p->prev;        delete p;        theSize--;        return retVal;    }
 iterator erase( iterator from, iterator to )    {        for(iterator itr=from; itr!=to; )            itr = erase(itr);        return to;    }