剖析容器List

来源:互联网 发布:淘宝福袋是死人衣服 编辑:程序博客网 时间:2024/06/09 09:20

List

零个或者多个数据元素的有限序列;

A. 是一个序列:元素之间有顺序,每一个元素都有前驱和后继;(这里的链表是一个带头节点的双向循环链表)

这里写图片描述

B. 有限的;
综上所述:ListNode的模型如下:

这里写图片描述

  1. 迭代器:一种遍历容器的方式,只作遍历,修改的作用,不析构节点;分为:普通迭代器(可读可改),const迭代器(可读不可改),反向迭代器(反向遍历);
  2. 模拟实现正向迭代器基本功能,代码如下:

这里写图片描述

template <class T>struct _ListNode{    T _data;    ListNode<T>* _prev;    ListNode<T>* _next;    _ListNode(const T& data)        :_data(data),_prev(NULL),_next(NULL)    {}    T& operator*()    {        return _data;    }};template <class T, class Ref, class Ptr>struct _ListIterator{    typedef _ListNode<T> Node;    typedef _ListIterator<T,Ref,Ptr> Self;    Node* _node;    _ListIterator(Node* node)        :_node(node)    {}    Self& operator++()//前置++    {        _node = _node->_next;        return *this;    }    Self operator++(int)//后置++    {        Self* cur(_node);        _node = _node->_next;        return cur;    }    Self& operator--()//前置--    {        _node = _node->_prev;        return *this;    }    Self operator--(int)//后置--    {        Self cur(_node);        _node = _node->_prev;        return cur;    }    Ref operator*()//Ref == T&    {        return _node->_data;    }    Ptr operator->()//返回了一个指针,其实就是如何将一个迭代器转化成一个指针,使其具有指针变量的属性    {        return &_node->_data;//返回了这个数的地址,将其赋给一个指针变量    }    bool operator!=(const Self& t) const    {        return _node != t._node;    }};//具有头节点的双向循环链表template <class T>class _List{    typedef _ListNode<T> Node;    typedef _ListIterator<T,T&,T*> Iterator;    typedef _ListIterator<T,const T&,const T*> IteratorConst;protected:    Node* _head;public:    Node* GetNode(const T& data)//这里表示让一个指针指向一个空间    {        return new Node(data);    }    _List()//这是一个含有头节点的双向链表,所以头节点也应该有空间,里面的存放的数据可以设置为默认值    {        _head = GetNode(T());//根据类型确定默认值        _head->_next = _head;        _head->_prev = _head;    }    ~_List()    {        _clear();        /*clear_Iterator();*/        delete _head;//头节点有空间必须要析构        _head = NULL;    }    //普通的迭代器    Iterator Begin()    {        return Iterator(_head->_next);    }    Iterator End()    {        return Iterator(_head);    }    //const迭代器    IteratorConst Begin() const    {        return IteratorConst(_head->_next);    }    IteratorConst End() const    {        return IteratorConst(_head);    }    //没有使用迭代器以前    Node* Find(const T& data)    {        Node* cur = _head->_next;        while(cur != _head)        {            if(*cur == data)                return cur;            cur = cur->_next;        }        return _head;    }    //使用迭代器以后    Iterator Find(const T& data)    {        Iterator it = Begin();        while(it != End())        {            if(*it == data)                return it;            ++it;        }        return it;    }    //没有使用迭代器之前    void _clear()    {        Node* cur = _head->_next;        while(cur != _head)        {            Node* del = cur;            cur = cur->_next;            delete del;        }        _head->_next = _head;        _head->_prev = _head;    }    //使用迭代器以后    void clear_Iterator()    {        Iterator cur = Begin();        while(cur != End())        {            Node* del = cur._node;            ++cur;            delete del;        }        _head->_next = _head;        _head->_prev = _head;    }    // 设计一个双向链表,实现随机位置的插入和删除,在pos的前面进行插入    void Insert(const Node* pos,const T& data)    {        assert(pos);        Node* cur = GetNode(data);        Node* pre = pos->_prev;        pre->_next = cur;        cur->_prev = pre;        cur->_next = pos;        pos->_prev = cur;    }    void Insert(Iterator pos, const T& data)    {        assert(pos._node);        Node* cur = GetNode(data);        Iterator pr = --pos;        pr._node->_next = cur;        cur->_prev = pr._node;        cur->_next = pos._node;        pos._node->_prev = cur;    }    Iterator Erase(Iterator& pos)//删除    {        assert(pos._node && pos == End());//_node不能为NULL,且不能删除_head节点        Iterator pre = --pos;        Iterator nex = ++pos;        pre._node->_next = nex._node;        nex._node->_prev = pre._node;        delete pos._node;        pos = pre;        return nex;    }    void PopFront()//头删    {        Erase(Begin());    }    void PopBack()//尾删    {        Erase(--End());    }    void PushFront(const T& data)//头插    {        Insert(Begin(),data);    }    void PushBack(const T& data)//尾插    {        Insert(End(),data);    }    bool IsEmpty()    {        return _head == _head->_next;    }    //模板内的成员函数也可以设计成模板函数    template <class InputIterator>    //将某个对象区间内的值拷贝到当前对象中    void Assign(InputIterator first,InputIterator last)//[)左闭右开的区间    {        _clear();//先清空再拷贝        while(first != last)        {            pubshBack(*first);//first进行*引用就取到了里面的data值了            ++first;        }    }};

3.迭代器失效问题:

这里写图片描述

4.反向迭代器:

这里写图片描述

不管是正向迭代器还是反向迭代器,在遍历我们的list中的元素时都是要从begin()所指向的那个节点开始的,然后一个一个往下执行,直到发现当前所指向的那个节点 == end()而结束;
对于反向迭代器而言,我们用begin()开始进行遍历的时候都是访问的是它所指向的下一个节点,在这里可能就比较绕了。这里的下一个节点我们使用”- -“的方式进行访问,那么你一定有疑问了,看图之后“- -”,那么就直接 == end()了,那么遍历才刚开始就结束了吗?当然不是,这里我们要注意,我们的下一个节点是针对正向迭代器而言的,正向迭代器的“- -”,就是反向迭代器的“++”。

这里写图片描述

代码如下:
充分利用正向迭代器进行函数的复用;

//反向迭代器:template <class Iterator>class ReverIterator{protected:    Iterator _current;    typedef ReverIterator<Iterator> Self;public:    ReverIterator(Iterator cur)        :_current(cur)    {}    Self& operator++()//前置++    {        --_current;//运用正向迭代器的--就是反向迭代器的++        return *this;    }    Self operator++(int)//后置++    {        ReverIterator re(_current);        --_current;        return re;    }    Self& operator--()//前置--    {        ++_current;        return *this;    }    Self operator--(int)//后置--    {        ReverIteratr cur(_current);        ++_current;        return cur;    }    //typename的意思是强调后面修饰的这个是一个类型,模板类的内嵌类型,用typename强调    typename Iterator::Reference operator*()    {        Iterator cur = _current;        return *(--cur);//访问当前指向的下一个值    }    typename Iterator::Pointer operator->()    {        return &operator*();    }    bool operator!=(const Self& cur)    {        return _current != cur._current;    }};
list中增添以下代码:    typedef ReverIterator<Iterator> ReIterator;    typedef ReverIterator<IteratorConst> ReIteratorConst;    ReIterator RBegin()    {        return ReIterator(End());    }    ReIterator REnd()    {        return ReIterator(Begin());    }    ReIteratorConst RBegin() const    {        return ReIteratorConst(End());    }    ReIteratorConst REnd() const    {        return ReIteratorConst(Begin());    }