【C++/STL】list(常见接口、模拟实现、反向迭代器、)

简介: 【C++/STL】list(常见接口、模拟实现、反向迭代器、)

list的底层是双向链表结构,双向链表中每个元素存储在互不相关的独立节点中,在节点中通过指针指向其前一个元素和后一个元素。

list的常见接口

对迭代器的封装

因为list的空间不是连续的,不能用原生指针,必须对其进行封装。

节点

重载->

当数据是自定义类型时,想通过->访问,就必须重载。

const迭代器

用const迭代器,需要重新弄一个类,而const迭代器跟普通迭代器基本一样,只修改了部分,如果为此就重新弄一个类,代码就太冗余了。

 下面是进行的优化:

本质相当于写了一个类模板,编译器实例化生成了两个类。

list与vector的对比

反向迭代器

反向迭代器的++就是正向迭代器的--,反向迭代器的--就是正向迭代器的++,因此反向迭代器的实现可以借助正向迭代器,即:反向迭代器内部可以包含一个正向迭代器,对正向迭代器的接口进行 包装即可。

反向迭代器完整代码

#pragma once 
 
//所以容器的反向迭代器
//迭代器适配器
namespace qjh
{
    //vector<T>::iterator
    template<class Iterator,class Ref,class Ptr>  //给谁的正向迭代器,就适配出对应的反向迭代器
    struct ReverseIterator   
    {
        typedef ReverseIterator<Iterator, Ref, Ptr> Self;
 
        Iterator _it;
        
        ReverseIterator(Iterator it)
            :_it(it)
        {}
 
        Ref operator*()
        {
            Iterator tmp = _it;  //不能修改_it,得用临时变量放回
            return *(--tmp);
        }
 
        Ptr operator->()
        {
            //return _it->;
            //return _it.operator->();
            return &(operator*());
        }
 
        Self& operator++()
        {
            --_it;
            return *this;
        }
 
        Self& operator--()
        {
            ++_it;
            return *this;
        }
 
        bool operator!=(const Self& s)
        {
            return _it != s._it;
        }
    };
}

list完整代码

#pragma once
#include<assert.h>
 
#include"ReverseIterator.h" 
 
namespace qjh
{
    template<class T>
    struct ListNode   //需要全部被公开,用struct
    {
        ListNode<T>* _next;
        ListNode<T>* _prev;
        T _data;
 
        ListNode(const T& x=T())
            :_next(nullptr)
            ,_prev(nullptr)
            ,_data(x)
        {}
    };
 
    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)
        {}
 
        //*it
        //T& operator*()
        Ref operator*()
        { 
            return _node->_data;
        }
 
        //T* operator->()
        Ptr operator->()
        {
            return  &_node->_data;
        }
 
        //++it
        Self& operator++()
        {
            _node = _node->_next;
            return *this;
        }
 
        //it++
        Self& operator++(int)
        {
            Self tmp(*this);
            _node = _node->_next;
            return tmp;
        }
 
        //--it
        Self& operator--()
        {
            _node = _node->_prev;
            return *this;
        }
 
        //it--
        Self& operator--(int)
        {
            Self tmp(*this);
            _node = _node->_prev;
            return tmp;
        }
 
        bool operator!=(const Self& it)
        {
            return _node != it._node;
        }
 
        bool operator==(const Self& it)
        {
            return _node == it._node;
        }
    };
 
    //template<class T>
    //struct ListConstIterator    //对指针进行封装,因为结点的空间不是连续的
    //{
    //  typedef ListNode<T> Node;
    //  typedef ListConstIterator<T> Self;
 
    //  Node* _node;
 
    //  ListConstIterator(Node* node)
    //      :_node(node)
    //  {}
 
    //  //*it
    //  const T& operator*()
    //  {
    //      return _node->_data;
    //  }
 
    //  const T* operator->()
    //  {
    //      return  &_node->_data;
    //  }
 
    //  //++it
    //  Self& operator++()
    //  {
    //      _node = _node->_next;
    //      return *this;
    //  }
 
    //  //it++
    //  Self& operator++(int)
    //  {
    //      Self tmp(*this);
    //      _node = _node->_next;
    //      return tmp;
    //  }
 
    //  //--it
    //  Self& operator--()
    //  {
    //      _node = _node->_prev;
    //      return *this;
    //  }
 
    //  //it--
    //  Self& operator--(int)
    //  {
    //      Self tmp(*this);
    //      _node = _node->_prev;
    //      return tmp;
    //  }
 
    //  bool operator!=(const Self& it)
    //  {
    //      return _node != it._node;
    //  }
 
    //  bool operator==(const Self& it)
    //  {
    //      return _node == it._node;
    //  }
    //};
 
    template<class T>
    class list
    {
        typedef ListNode<T> Node;
    public:
        /*typedef ListIterator<T> iterator;
        typedef ListConstIterator<T> const_iterator;*/
 
        typedef ListIterator<T,T&,T*> iterator;
        typedef ListIterator<T,const T&,const T*> const_iterator;
 
        typedef ReverseIterator<iterator, T&, T*> reverse_iterator;
        typedef ReverseIterator<const_iterator, const T&, const T*> const_reverse_iterator;
 
 
        reverse_iterator rbegin()
        {
            return reverse_iterator(end());
        }
 
        reverse_iterator rend()
        {
            return reverse_iterator(begin());
        }
 
        iterator begin()
        {
            return iterator(_head->_next);
        }
 
        iterator end()
        {
            return iterator(_head);
        }
 
        //const迭代器需要迭代器指向的内容不能修改!const iterator不是我们需要的const迭代器
        //const 迭代器本身可以++等操作
        const_iterator begin() const
        {
            return const_iterator(_head->_next);
        }
 
        const_iterator end() const
        {
            return const_iterator(_head);
        }
 
        void empty_init()
        {
            _head = new Node;
            _head->_next = _head;
            _head->_prev = _head;
 
            _size = 0;
        }
 
        list()
        {
            empty_init();
        }
 
        list(initializer_list<int> il)
        {
            empty_init();
 
            for (auto& e : il)
            {
                push_back(e);
            }
        }
 
        //lt2(lt1)
        list(const list<T>& lt)
        {
            empty_init();
            for (auto& e : lt)
            {
                push_back(e);
            }
        }
 
        void swap(list<T>& lt)
        {
            std::swap(_head, lt._head);
            std::swap(_size, lt._size);
        }
 
        //lt1=lt3
        list<T>& operator=(list<T> lt)
        {
            swap(lt);
            return *this;
        }
 
        void clear()
        {
            iterator it = begin();
            while (it != end())
            {
                it = erase(it);
            }
        }
 
        ~list()
        {
            clear();
            delete _head;
            _head = nullptr;
        }
 
 
        //void push_back(const T& x)
        //{
        //  Node* newnode = new Node(x);
        //  Node* tail = _head->_prev;
 
        //  tail->_next = newnode;
        //  newnode->_prev = tail;
        //  newnode->_next = _head;
        //  _head->_prev = newnode;
        //}
 
        void push_back(const T& x)
        {
            insert(end(), x);
        }
 
        void push_front(const T& x)
        {
            insert(begin(), x);
        }
 
        void pop_back()
        {
            erase(--end());//迭代器不能-1,只能用-- 
        }
 
        void pop_front()
        {
            erase(begin());
        }
 
        void insert(iterator pos, const T& val)
        {
            Node* cur = pos._node;
            Node* newnode = new Node(val);
            Node* prev = cur->_prev;
 
            prev->_next = newnode;
            newnode->_prev = prev;
            newnode->_next = cur;
            cur->_prev = newnode;
            _size++;
        }
 
        iterator erase(iterator pos) //节点失效了,需要返回下一个节点
        {
            Node* cur = pos._node;
            Node* prev = cur->_prev;
            Node* next = cur->_next;
 
            prev->_next = next;
            next->_prev = prev;
            delete cur;
            _size--;
            return iterator(next); //匿名对象
        }
 
        size_t size() const
        {
            return _size;
        }
 
        bool empty()
        {
            return _size == 0;
        }
 
    private:
        Node* _head;
        size_t _size;
    };
 
 
    void test_list1()
    {
        list<int> lt;
        lt.push_back(1);
        lt.push_back(2);
        lt.push_back(3);
        lt.push_back(4);
        lt.push_back(5);
 
        list<int>::iterator it = lt.begin();
        while (it != lt.end())
        {
            cout << *it << " ";
            ++it;
        }
        cout << endl;
 
        lt.push_front(10);
        lt.push_front(20);
        lt.push_front(30);
 
        for (auto e : lt)
        {
            cout << e << " ";
        }
        cout << endl;
 
        lt.pop_back();
        lt.pop_back();
        lt.pop_front();
        lt.pop_front();
 
        for (auto e : lt)
        {
            cout << e << " ";
        }
        cout << endl;
 
    }
 
    struct A
    {
        int _a1;
        int _a2;
 
        A(int a1 = 0, int a2 = 0)
            :_a1(a1)
            ,_a2(a2)
        {}
    }; 
 
    void test_list2()
    {
        list<A> lt;
        A aa1(1, 1);
        A aa2 = { 1, 1 };
 
        lt.push_back(aa1);
        lt.push_back(aa2);
        lt.push_back(A(2,2));
        lt.push_back({3,3});
        lt.push_back({4,4});
 
        list<A>::iterator it = lt.begin();
        while (it != lt.end())
        { 
            //cout << (*it)._a1 << ":" << (*it)._a2 << endl;
            //cout << it->_a1 << ":" << it->_a2 << endl;    //如果要遍历自定义类型,就要重载->,编译器为了可读性,省略了一个->
            cout << it.operator->()->_a1 << ":" << it.operator->()->_a2 << endl;
            ++it;
        }
        cout << endl;
    }
 
    void PrintList(const list<int>& clt)
    {
        list<int>::const_iterator it = clt.begin();
        while (it != clt.end())
        {
            //*it += 10; 
 
            cout << *it << " ";
            ++it;
        }
        cout << endl;
    }
 
    void test_list3()
    {
        list<int> lt;
        lt.push_back(1);
        lt.push_back(2);
        lt.push_back(3);
        lt.push_back(4);
        lt.push_back(5);
 
        PrintList(lt);
 
        list<int> lt1(lt);
        PrintList(lt1);
 
    }
}


目录
相关文章
|
1月前
|
存储 程序员 C++
C++常用基础知识—STL库(2)
C++常用基础知识—STL库(2)
68 5
|
1月前
|
存储 自然语言处理 程序员
C++常用基础知识—STL库(1)
C++常用基础知识—STL库(1)
52 1
|
1月前
|
算法 安全 Linux
【C++STL简介】——我与C++的不解之缘(八)
【C++STL简介】——我与C++的不解之缘(八)
|
1月前
|
算法 数据处理 C++
c++ STL划分算法;partition()、partition_copy()、stable_partition()、partition_point()详解
这些算法是C++ STL中处理和组织数据的强大工具,能够高效地实现复杂的数据处理逻辑。理解它们的差异和应用场景,将有助于编写更加高效和清晰的C++代码。
22 0
|
6天前
|
存储 编译器 C++
【c++】类和对象(中)(构造函数、析构函数、拷贝构造、赋值重载)
本文深入探讨了C++类的默认成员函数,包括构造函数、析构函数、拷贝构造函数和赋值重载。构造函数用于对象的初始化,析构函数用于对象销毁时的资源清理,拷贝构造函数用于对象的拷贝,赋值重载用于已存在对象的赋值。文章详细介绍了每个函数的特点、使用方法及注意事项,并提供了代码示例。这些默认成员函数确保了资源的正确管理和对象状态的维护。
29 4
|
7天前
|
存储 编译器 Linux
【c++】类和对象(上)(类的定义格式、访问限定符、类域、类的实例化、对象的内存大小、this指针)
本文介绍了C++中的类和对象,包括类的概念、定义格式、访问限定符、类域、对象的创建及内存大小、以及this指针。通过示例代码详细解释了类的定义、成员函数和成员变量的作用,以及如何使用访问限定符控制成员的访问权限。此外,还讨论了对象的内存分配规则和this指针的使用场景,帮助读者深入理解面向对象编程的核心概念。
23 4
|
30天前
|
存储 编译器 对象存储
【C++打怪之路Lv5】-- 类和对象(下)
【C++打怪之路Lv5】-- 类和对象(下)
26 4
|
30天前
|
编译器 C语言 C++
【C++打怪之路Lv4】-- 类和对象(中)
【C++打怪之路Lv4】-- 类和对象(中)
23 4
|
29天前
|
存储 安全 C++
【C++打怪之路Lv8】-- string类
【C++打怪之路Lv8】-- string类
21 1
|
1月前
|
存储 编译器 C++
【C++类和对象(下)】——我与C++的不解之缘(五)
【C++类和对象(下)】——我与C++的不解之缘(五)