剖析容器List

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());
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值