模板类模拟实现List

来源:互联网 发布:加工中心手动编程铣圆 编辑:程序博客网 时间:2024/05/23 11:01

  上一篇中我模拟实现了vector,接着这个当然就是list了,首先对于list,在库函数里面,list是一个双向的,即既含有next域,也含有prev域,每个节点都含有这样的结构,我们在写的时候要把一个一个链接上,而且要保证逻辑正确,作者本人就在拷贝构造函数的时候懵逼了半天。所以一个表示节点的结构体必须有,这个当然也可以用类,但是你会感觉本质上你还是用类中结构体的性质,所以还是结构体方便一点。
  

template<class T>struct ListNode{    ListNode(const T& x = T())      //构造函数,给_prev,_next,_value初始化    : _prev(0)    , _next(0)    , _value(x)    { }    ListNode<T>* _prev;    ListNode<T>* _next;    T _value;};

  这个想必大家都很熟悉,所以我就不多说了,然后为了更好、更快捷、明了的表示一个节点,或者是对这个节点做一些操作,我们最好在封装一个类,确实,我是按库里面写的,库里也包含了这个类,采用了迭代器的用法,目前,我们只当迭代器是一个指针,这样才能更直观的理解我们现在的用法。

  和库里面一样,我也把很多类型名定义成自己顺手的自定义类型。

template<class T, class Ref, class Ptr>struct __ListIterator__{    typedef __ListIterator__<T, T&, T*> Iterator;    typedef __ListIterator__<const T, const T&, const T*> ConstItrator;    typedef __ListIterator__<T, Ref, Ptr> Self;    typedef T ValueType;    typedef Ref Reference;    typedef Ptr Pointer;    typedef ListNode<T>*  LinkType;    typedef size_t SizeType;    LinkType _node;public:    __ListIterator__(LinkType x)        :_node(x)    { }    __ListIterator__()        :_node(0)    { }    __ListIterator__(const Iterator& x)        :_node(x._node)    { }    bool operator==(const Iterator& x)    {        return x._node == _node;    }    bool operator!=(const Iterator& x)    {        return x._node != _node;    }    Reference operator*()    {        return _node->_value;    }    Pointer operator->()    {        return &(*(_node->_value));    }    Self& operator++()    {        _node = _node->_next;        return *this;    }    Self operator++(int)    {        Self temp(*this);        _node = _node->_next;        return temp;    }    Self& operator--()    {        _node = _node->_prev;        return *this;    }    Self operator--(int)    {        Self temp(*this);        _node = _node->_prev;        return temp;    }};

  最后就该到list的模板类了,这才是重中之重,我也是到这里迷失了一段时间,一个函数改了好久,几近崩溃(小白吐槽而已)。不说了,对这代码再给你说说我的逻辑。

template<class T>class List{public:    typedef ListNode<T> Node;    typedef T ValueType;    typedef ValueType* Pointer;    typedef const ValueType* ConstPointer;    typedef ValueType& Reference;    typedef const ValueType& ConstReference;    typedef Node* LinkType;    typedef size_t SizeType;    typedef __ListIterator__<T, T&, T*> Iterator;    typedef __ListIterator__<const T, const T&, const T*> ConstIterator;

   //无参的构造函数,当然一进去就要先开辟好空间
   //等着其他的函数什么调用的时候有插入、删除的空间
   //并且要构成一个环,

   这里写图片描述
  

    List<T>()    {       _node = new Node;        _node->_next = _node;        _node->_prev = _node;        _node->_value = 0;    }

  这个函数让我很是尴尬,我的思维逻辑很清晰,在这个函数出错的时候,我还专门找人讨论我的逻辑,绝对没毛病,但是就是有问题,索性放着美观,过了一天,早上打开又理了一次,一次就出来了。所以我get到了一个技能,有时候,歇一歇,放松一下对自己也有帮助。

    List<T>(const List<T>& l)    {        _node = new Node;//给this的_node先开辟好空间        LinkType MoveNode = _node;//然后新定义一个节点,表示尾节点        LinkType srcNode = new Node;        srcNode = l._node;//创建一个节点,表示被拷贝对象的头结点        LinkType destNode = new Node;//创建新节点,用来储存拷贝节点的数据,再链接到尾节点上        while (srcNode->_next != l._node)//当l的最后一个节点被拷贝完后,停止拷贝        {            destNode = new Node;//每次进去:开辟空间->储存数具->链接上尾节点            MoveNode->_next = destNode;            destNode->_prev = MoveNode;            destNode->_next = _node;            _node->_prev = destNode;            srcNode = srcNode->_next;            MoveNode = MoveNode->_next;        }    }

示意图:
插入一个节点
这里写图片描述
插入两个节点
这里写图片描述
以此类推,每次进来先和尾节点的next域相连,然后把新节点的prev域指向尾节点,还要记得的是,一定要和头结点相连,即上述操作完成之后,将新节点的next域指向头结点,将头结点的prev域指向尾节点,这样才是一个循环的双向链表,假如你本意不循环的话,让我没说,但是记得你的节点的netx域要指空。

赋值运算符的操作没啥说的,和拷贝构造的一样,多加个返回值而已,最起码这个函数是这样。逻辑都是一样的。

    List<T>& operator=(const List& l)    {        _node = new Node;        LinkType MoveNode = _node;        LinkType srcNode = new Node;        srcNode = l._node;        LinkType destNode = new Node;        while (srcNode->_next != l._node)        {            destNode = new Node;            destNode->_value = srcNode->_next->_value;            MoveNode->_next = destNode;            destNode->_prev = MoveNode;            destNode->_next = _node;            _node->_prev = destNode;            srcNode = srcNode->_next;            MoveNode = MoveNode->_next;        }        return *this;    }

这里写代码片

    Iterator Insert(Iterator pos, const T& x)    //插入函数,在pos位置的前面插入    {        LinkType temp = new Node(x);        pos._node->_prev->_next = temp;        temp->_prev = pos._node->_prev;        temp->_next = pos._node;        pos._node->_prev = temp;        return temp;    }

删除节点的图解:
这里写代码片

    Iterator Erase(const T& value)    {        Iterator pos = Find(value);        Iterator temp = pos;        temp++;        pos._node->_prev->_next = pos._node->_next;        pos._node->_next->_prev = pos._node->_prev;        delete pos._node;        return temp;    }    Iterator Begin()    {        return _node->_next;    }    ConstIterator Begin()const    {        return _node->_next;    }    Iterator End()    {        return _node;    }    ConstIterator End()const    {        return _node;    }    bool Empty()const    {        return Begin() == End();    }    SizeType Size()    {        SizeType size = 0;        Iterator temp = Begin();        while (temp._node != _node)        {            temp._node = temp._node->_next;            size++;        }        return size;    }    Reference Front()    {        return _node->_next->_value;    }    ConstReference Front()const    {        return _node->_next->_value;    }    Reference Back()    {        return _node->_prev->_value;    }    ConstReference Back()const    {        return _node->_prev->_value;    }    void PushFront(const T& x)    {        Insert(Begin(), x);    }    void PushBack(const T& x)    {        Insert(End(), x);    }    void PopFront()    {        Delete(_node->_next);    }    void PopBack()    {        Delete(_node->_prev);    }    void Delete(Iterator pos)    {        Iterator temp = pos;        temp._node->_prev->_next = temp._node->_next;        temp._node->_next->_prev = temp._node->_prev;        delete temp._node;    }    void Clear()    {        while (Begin() != End())        {            Delete(Begin());        }        _node->_next = _node;        _node->_prev = _node;        _node->_value = 0;    }    ~List()    {        Iterator temp;        Clear();    }    friend ostream& operator<<(ostream& os, List<T>& L)    {        Iterator temp = L.Begin();        Iterator END = L.End();        while (temp._node != END._node)        {            cout << temp._node->_value << " ";            temp._node = temp._node->_next;        }        return os;    }protected:    Iterator Find(const T& value)    {        Iterator temp = _node;        while (temp._node->_value != value)        {            temp._node = temp._node->_next;        }        return temp;    }private:    LinkType _node;};
0 0