【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);
 
    }
}


目录
相关文章
|
2月前
|
存储 算法 C++
C++ STL 初探:打开标准模板库的大门
C++ STL 初探:打开标准模板库的大门
116 10
|
7天前
|
算法 C语言 C++
【c++丨STL】list的使用
本文介绍了STL容器`list`的使用方法及其主要功能。`list`是一种双向链表结构,适用于频繁的插入和删除操作。文章详细讲解了`list`的构造函数、析构函数、赋值重载、迭代器、容量接口、元素访问接口、增删查改操作以及一些特有的操作接口如`splice`、`remove_if`、`unique`、`merge`、`sort`和`reverse`。通过示例代码,读者可以更好地理解如何使用这些接口。最后,作者总结了`list`的特点和适用场景,并预告了后续关于`list`模拟实现的文章。
22 7
|
24天前
|
存储 编译器 C语言
【c++丨STL】vector的使用
本文介绍了C++ STL中的`vector`容器,包括其基本概念、主要接口及其使用方法。`vector`是一种动态数组,能够根据需要自动调整大小,提供了丰富的操作接口,如增删查改等。文章详细解释了`vector`的构造函数、赋值运算符、容量接口、迭代器接口、元素访问接口以及一些常用的增删操作函数。最后,还展示了如何使用`vector`创建字符串数组,体现了`vector`在实际编程中的灵活性和实用性。
49 4
|
26天前
|
C语言 C++ 容器
【c++丨STL】string模拟实现(附源码)
本文详细介绍了如何模拟实现C++ STL中的`string`类,包括其构造函数、拷贝构造、赋值重载、析构函数等基本功能,以及字符串的插入、删除、查找、比较等操作。文章还展示了如何实现输入输出流操作符,使自定义的`string`类能够方便地与`cin`和`cout`配合使用。通过这些实现,读者不仅能加深对`string`类的理解,还能提升对C++编程技巧的掌握。
55 5
|
26天前
|
存储 编译器 C语言
【c++丨STL】string类的使用
本文介绍了C++中`string`类的基本概念及其主要接口。`string`类在C++标准库中扮演着重要角色,它提供了比C语言中字符串处理函数更丰富、安全和便捷的功能。文章详细讲解了`string`类的构造函数、赋值运算符、容量管理接口、元素访问及遍历方法、字符串修改操作、字符串运算接口、常量成员和非成员函数等内容。通过实例演示了如何使用这些接口进行字符串的创建、修改、查找和比较等操作,帮助读者更好地理解和掌握`string`类的应用。
42 2
|
1月前
|
存储 算法 Linux
【c++】STL简介
本文介绍了C++标准模板库(STL)的基本概念、组成部分及学习方法,强调了STL在提高编程效率和代码复用性方面的重要性。文章详细解析了STL的六大组件:容器、算法、迭代器、仿函数、配接器和空间配置器,并提出了学习STL的三个层次,旨在帮助读者深入理解和掌握STL。
48 0
|
10天前
|
存储 编译器 C语言
【c++丨STL】vector模拟实现
本文深入探讨了 `vector` 的底层实现原理,并尝试模拟实现其结构及常用接口。首先介绍了 `vector` 的底层是动态顺序表,使用三个迭代器(指针)来维护数组,分别为 `start`、`finish` 和 `end_of_storage`。接着详细讲解了如何实现 `vector` 的各种构造函数、析构函数、容量接口、迭代器接口、插入和删除操作等。最后提供了完整的模拟实现代码,帮助读者更好地理解和掌握 `vector` 的实现细节。
21 0
|
2月前
|
存储 搜索推荐 C++
【C++篇】深度剖析C++ STL:玩转 list 容器,解锁高效编程的秘密武器2
【C++篇】深度剖析C++ STL:玩转 list 容器,解锁高效编程的秘密武器
62 2
【C++篇】深度剖析C++ STL:玩转 list 容器,解锁高效编程的秘密武器2
|
2月前
|
存储 程序员 C++
C++常用基础知识—STL库(2)
C++常用基础知识—STL库(2)
82 5
|
2月前
|
存储 自然语言处理 程序员
C++常用基础知识—STL库(1)
C++常用基础知识—STL库(1)
74 1