C++ list【常用接口、模仿实现等】

打印 上一主题 下一主题

主题 667|帖子 667|积分 2001

1. list的先容及使用

1.1 list的先容

1.list是可以在常数范围内涵恣意位置举行插入和删除的序列式容器,而且该容器可以前后双向迭代。
2.list的底层是双向链表结构,双向链表中每个元素存储在互不相关的独立节点中,在节点中通过指针指向其前一个元素和后一个元素。
3.list与forward_list非常相似,最主要的差别在于forward_list是单链表,只能朝前迭代,让其更简单高效。
4.与其他的序列式容器相比(array,_vector,deque),list通常在恣意位置举行插入、移除元素的执行效率更好。
5.与其他序列式容器相比,list和forward_list最大的缺陷是不支持恣意位置的随机访问,好比:要访问list的第六个元素,必须从已知的位置(好比头部或尾部)迭代到该位置,在这段位置上迭代器需要线性的时间开销;list还需要一些额外的空间,以保存每个节点的相关联信息。
 

1.2 list的使用

1.2.1 list的构造

析构函数(constructor)

接口说明

list (size_type n, const value_type& val = value_type())构造的list中包含n个值为val的元素
list()构造空的list
list (const list& x)拷贝构造函数
list (InputIterator first, InputIterator last)用[first, last)区间中的元素构造list
(若为手机阅读,表格可左右移动)


1.2.2 list iterato的使用

此处,各人可暂时将迭代器理解成一个指针,该指针指向list中的某个节点。
函数声明

接口说明

begin+end返回第一个元素的迭代器+返回最后一个元素下一个位置的迭代器
rbegin+rend返回第一个元素的reverse_iterator,即end位置,返回最后一个元素下一个位置的reverse_iterator,即beign位置
 (若为手机阅读,表格可左右移动)

    【注意】
  1. begin与end为正向迭代器,对迭代器执行++操纵,迭代器向后移动
  2. rbegin(end)与rend(begin)为反向迭代器,对迭代器执行++操纵,迭代器向前移动
  


1.2.3 list capacity

函数声明

接口说明

empty检测list是否为空,是返回true,否则返回false
size返回list中有用节点的个数
 (若为手机阅读,表格可左右移动)


1.2.4 list element access

函数声明

接口说明

front返回list的第一个节点中值的引用
back返回list的最后一个节点中值的引用
 (若为手机阅读,表格可左右移动)


1.2.5 list modifiers

函数声明

接口说明

push_front在list首元素前插入值为val的元素
pop_front删除list中的第一个元素
push_back在list尾部插入值为val的元素
pop_back删除list中最后一个元素
insert在list position位置中插入值为val的元素
erase删除list position位置的元素
swap交换两个list中的元素
clear清空list中的有用元素
(若为手机阅读,表格可左右移动)



1.2.6 list的迭代器失效

 前面说过,此处各人可将迭代器暂时理解成类似于指针,迭代器失效即迭代器所指向的节点的无效,即该节点被删除了。因为list的底层结构为带头结点的双向循环链表,因此在list中举行插入时是不会导致list的迭代器失效的,只有在删除时才会失效,而且失效的只是指向被删除节点的迭代器,其他迭代器不会受到影响。
错误:

改正:

2. list的模仿实现

   实现节点类
  

  1. template<class T>
  2. struct ListNode
  3. {
  4.         ListNode<T>* _next;
  5.         ListNode<T>* _prev;
  6.         T _data;
  7.         ListNode(const T& data = T())
  8.                 :_next(nullptr)
  9.                 , _prev(nullptr)
  10.                 , _data(data)
  11.         {
  12.         }
  13. };
复制代码
   实现正向迭代器 
  迭代器不消实现析构函数和深拷贝。因为迭代器本身就是为了访问链表的节点,节点属于链表,不属于迭代器,如果需要析构和深拷贝,应该在控制链表的类中实现。
  

  1.         template<class T, class Ref, class Ptr>
  2.         struct ListIterator
  3.         {
  4.                 typedef ListNode<T> Node;
  5.                 typedef ListIterator<T, Ref, Ptr> self;
  6.                 Node* _node;
  7.                 ListIterator(Node* node)
  8.                         :_node(node)
  9.                 {
  10.                 }
  11.                 self& operator++()
  12.                 {
  13.                         _node = _node->_next;
  14.                         return *this;
  15.                 }
  16.                 self operator++(int)
  17.                 {
  18.                         self tmp(*this);
  19.                         _node = _node->_next;
  20.                         return tmp;
  21.                 }
  22.                 self& operator--()
  23.                 {
  24.                         _node = _node->_prev;
  25.                         return *this;
  26.                 }
  27.                 self operator--(int)
  28.                 {
  29.                         self tmp(*this);
  30.                         _node = _node->_prev;
  31.                         return tmp;
  32.                 }
  33.                 Ref operator*()
  34.                 {
  35.                         return _node->_data;
  36.                 }
  37.                 bool operator!=(const self& it)
  38.                 {
  39.                         return _node != it._node;
  40.                 }
  41.                 bool operator==(const self& it)
  42.                 {
  43.                         return _node == it._node;
  44.                 }
  45.                 Ptr operator->()
  46.                 {
  47.                         return &_node->_data;
  48.                 }
  49.         };
复制代码
    实现反向迭代器
  1. template<class T, class Ref, class Ptr>
  2. struct RListIterator
  3. {
  4.         typedef ListNode<T> Node;
  5.         typedef RListIterator<T, Ref, Ptr> self;
  6.         Node* _node;
  7.         RListIterator(Node* node)
  8.                 :_node(node)
  9.         {
  10.         }
  11.         self& operator++()
  12.         {
  13.                 _node = _node->_prev;
  14.                 return *this;
  15.         }
  16.         self operator++(int)
  17.         {
  18.                 self tmp(*this);
  19.                 _node = _node->_prev;
  20.                 return tmp;
  21.         }
  22.         self& operator--()
  23.         {
  24.                 _node = _node->_next;
  25.                 return *this;
  26.         }
  27.         self operator--(int)
  28.         {
  29.                 self tmp(*this);
  30.                 _node = _node->_next;
  31.                 return tmp;
  32.         }
  33.         Ref operator*()
  34.         {
  35.                 return _node->_data;
  36.         }
  37.         bool operator!=(const self& it)
  38.         {
  39.                 return _node != it._node;
  40.         }
  41.         bool operator==(const self& it)
  42.         {
  43.                 return _node == it._node;
  44.         }
  45.         Ptr operator->()
  46.         {
  47.                 return &_node->_data;
  48.         }
  49. };
复制代码
   实现控制list的类
  

  

  1. template<class T>
  2. class list
  3. {
  4.         typedef ListNode<T> Node;
  5. public:
  6.         typedef ListIterator<T, T&, T*> iterator;
  7.         typedef RListIterator<T, T&, T*> reverse_iterator;
  8.         typedef ListIterator<T, const T&, const T*> const_iterator;
  9.         void empty_init()
  10.         {
  11.                 _head = new Node();
  12.                 _head->_next = _head;
  13.                 _head->_prev = _head;
  14.         }
  15.         list()
  16.         {
  17.                 empty_init();
  18.         }
  19.         list(const list<T>& it)
  20.         {
  21.                 empty_init();
  22.                 for (const auto& e : it)
  23.                 //在范围for上加上引用,如果it内的元素体积很大的话可以减小代价,引用并不会导致浅拷贝
  24.                 //eg:int a=1;int& a1=a;int b=a1;变量b只是和a的值一样并没有指向同一块空间(int b=a;)
  25.                 {
  26.                         push_back(e);
  27.                 }
  28.         }
  29.         list(initializer_list<T> il)
  30.         {
  31.                 empty_init();
  32.                 for (const auto& e : il)
  33.                 {
  34.                         push_back(e);
  35.                 }
  36.         }
  37.         ~list()
  38.         {
  39.                 clear();
  40.                 delete _head;
  41.                 _head = nullptr;
  42.         }
  43.         void clear()
  44.         {
  45.                 auto it = begin();
  46.                 while (it != end())
  47.                 {
  48.                         it = erase(it);
  49.                 }
  50.         }
  51.         list<T>& operator=(list<T> it)
  52.         {
  53.                 std::swap(_head, it._head);
  54.                 return *this;
  55.         }
  56.         iterator begin()
  57.         {
  58.                 return iterator(_head->_next);
  59.         }
  60.         const_iterator begin() const
  61.         {
  62.                 return const_iterator(_head->_next);
  63.         }
  64.         iterator end()
  65.         {
  66.                 return iterator(_head);
  67.         }
  68.         const_iterator end() const
  69.         {
  70.                 return const_iterator(_head);
  71.         }
  72.         reverse_iterator rbegin()
  73.         {
  74.                 return reverse_iterator(_head->_prev);
  75.         }
  76.         reverse_iterator rend()
  77.         {
  78.                 return reverse_iterator(_head);
  79.         }
  80.         void push_back(const T& x)
  81.         {
  82.                 //Node* newnode = new Node(x);
  83.                 //Node* tail = _head->_prev;
  84.                 //tail->_next = newnode;
  85.                 //newnode->_prev = tail;
  86.                 //newnode->_next = _head;
  87.                 //_head->_prev = newnode;
  88.                 insert(end(), x);
  89.         }
  90.         void pop_back()
  91.         {
  92.                 erase(--end());
  93.         }
  94.         void push_front(const T& x)
  95.         {
  96.                 insert(begin(), x);
  97.         }
  98.         void pop_front()
  99.         {
  100.                 erase(begin());
  101.         }
  102.         iterator insert(iterator pos, const T& x)
  103.         {
  104.                 Node* cur = pos._node;
  105.                 Node* newnode = new Node(x);
  106.                 Node* prev = cur->_prev;
  107.                 prev->_next = newnode;
  108.                 newnode->_prev = prev;
  109.                 newnode->_next = cur;
  110.                 cur->_prev = newnode;
  111.                 return iterator(newnode);
  112.         }
  113.         iterator erase(iterator pos)
  114.         {
  115.                 assert(pos != end());
  116.                 Node* cur = pos._node;
  117.                 Node* prev = cur->_prev;
  118.                 Node* next = cur->_next;
  119.                 prev->_next = next;
  120.                 next->_prev = prev;
  121.                 delete cur;
  122.                 return iterator(next);
  123.         }
  124. private:
  125.         Node* _head;
  126. };
复制代码
 完整list.h
  1. #pragma once#include <assert.h>namespace wmm{        template<class T>        struct ListNode        {                ListNode<T>* _next;                ListNode<T>* _prev;                T _data;                ListNode(const T& data = T())                        :_next(nullptr)                        , _prev(nullptr)                        , _data(data)                {                }        };        template<class T, class Ref, class Ptr>        struct RListIterator        {                typedef ListNode<T> Node;                typedef RListIterator<T, Ref, Ptr> self;                Node* _node;                RListIterator(Node* node)                        :_node(node)                {                }                self& operator++()                {                        _node = _node->_prev;                        return *this;                }                self operator++(int)                {                        self tmp(*this);                        _node = _node->_prev;                        return tmp;                }                self& operator--()                {                        _node = _node->_next;                        return *this;                }                self operator--(int)                {                        self tmp(*this);                        _node = _node->_next;                        return tmp;                }                Ref operator*()                {                        return _node->_data;                }                bool operator!=(const self& it)                {                        return _node != it._node;                }                bool operator==(const self& it)                {                        return _node == it._node;                }                Ptr operator->()                {                        return &_node->_data;                }        };        template<class T, class Ref, class Ptr>
  2.         struct ListIterator
  3.         {
  4.                 typedef ListNode<T> Node;
  5.                 typedef ListIterator<T, Ref, Ptr> self;
  6.                 Node* _node;
  7.                 ListIterator(Node* node)
  8.                         :_node(node)
  9.                 {
  10.                 }
  11.                 self& operator++()
  12.                 {
  13.                         _node = _node->_next;
  14.                         return *this;
  15.                 }
  16.                 self operator++(int)
  17.                 {
  18.                         self tmp(*this);
  19.                         _node = _node->_next;
  20.                         return tmp;
  21.                 }
  22.                 self& operator--()
  23.                 {
  24.                         _node = _node->_prev;
  25.                         return *this;
  26.                 }
  27.                 self operator--(int)
  28.                 {
  29.                         self tmp(*this);
  30.                         _node = _node->_prev;
  31.                         return tmp;
  32.                 }
  33.                 Ref operator*()
  34.                 {
  35.                         return _node->_data;
  36.                 }
  37.                 bool operator!=(const self& it)
  38.                 {
  39.                         return _node != it._node;
  40.                 }
  41.                 bool operator==(const self& it)
  42.                 {
  43.                         return _node == it._node;
  44.                 }
  45.                 Ptr operator->()
  46.                 {
  47.                         return &_node->_data;
  48.                 }
  49.         };        template<class T>        class list        {                typedef ListNode<T> Node;        public:                typedef ListIterator<T, T&, T*> iterator;                typedef RListIterator<T, T&, T*> reverse_iterator;                typedef ListIterator<T, const T&, const T*> const_iterator;                void empty_init()                {                        _head = new Node();                        _head->_next = _head;                        _head->_prev = _head;                }                list()                {                        empty_init();                }                list(const list<T>& it)                {                        empty_init();                        for (const auto& e : it)                         //在范围for上加上引用,如果it内的元素体积很大的话可以减小代价,引用并不会导致浅拷贝                        //eg:int a=1;int& a1=a;int b=a1;变量b只是和a的值一样并没有指向同一块空间(int b=a;)                        {                                push_back(e);                        }                }                list(initializer_list<T> il)                {                        empty_init();                        for (const auto& e : il)                        {                                push_back(e);                        }                }                ~list()                {                        clear();                        delete _head;                        _head = nullptr;                }                void clear()                {                        auto it = begin();                        while (it != end())                        {                                it = erase(it);                        }                }                list<T>& operator=(list<T> it)                {                        std::swap(_head, it._head);                        return *this;                }                iterator begin()                {                        return iterator(_head->_next);                }                const_iterator begin() const                {                        return const_iterator(_head->_next);                }                iterator end()                {                        return iterator(_head);                }                const_iterator end() const                {                        return const_iterator(_head);                }                reverse_iterator rbegin()                {                        return reverse_iterator(_head->_prev);                }                reverse_iterator rend()                {                        return reverse_iterator(_head);                }                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;                        insert(end(), x);                }                void pop_back()                {                        erase(--end());                }                void push_front(const T& x)                {                        insert(begin(), x);                }                void pop_front()                {                        erase(begin());                }                iterator insert(iterator pos, const T& x)                {                        Node* cur = pos._node;                        Node* newnode = new Node(x);                        Node* prev = cur->_prev;                        prev->_next = newnode;                        newnode->_prev = prev;                        newnode->_next = cur;                        cur->_prev = newnode;                        return iterator(newnode);                }                iterator erase(iterator pos)                {                        assert(pos != end());                        Node* cur = pos._node;                        Node* prev = cur->_prev;                        Node* next = cur->_next;                        prev->_next = next;                        next->_prev = prev;                        delete cur;                        return iterator(next);                }        private:                Node* _head;        };        //遍历测试        void test()        {                list<int> l;                l.push_back(1);                l.push_back(2);                l.push_back(3);                l.push_back(4);                list<int>::iterator it = l.begin();                while (it != l.end())                {                        cout << *it << endl;                        ++it;                }        }        //结构体数据,重载符号->测试        struct pos        {                int _x;                int _y;                pos(int x = 0, int y = 0)                        :_x(x)                        , _y(y)                {                }        };        void test2()        {                list<pos> l;                struct pos* a = (struct pos*)malloc(sizeof(struct pos));                a->_x = 200;                a->_y = 200;                struct pos b;                b._x = 300;                b._y = 300;                l.push_back(pos(100, 100));                l.push_back(*a);                l.push_back(b);                list<pos>::iterator it = l.begin();                while (it != l.end())                {                        cout << (*it)._x << endl;                        cout << (*it)._y << endl;                        cout << it._node->_data._x << endl;                        cout << it._node->_data._y << endl;                        cout << it->_x << endl;                        cout << it->_y << endl;                        //想让迭代器it像结构体指针一样访问数据,重载了一个->符号                        ++it;                }        }        //erase insert 测试        void test3()        {                list<int> l;                l.push_back(1);                l.push_back(2);                l.push_back(3);                l.push_back(4);                list<int>::iterator it = l.begin();                it=l.erase(it);//注意迭代器失效问题                for (auto e : l)                {                        cout << e << endl;                }                cout << endl;                //it=l.begin();                l.insert(it, 1);                for (auto& e : l)                {                        cout << e << endl;                        e = 3;                }        }        //拷贝构造测试        void test4()        {                list<int> l;                l.push_back(1);                l.push_back(2);                l.push_back(3);                l.push_back(4);                for (auto e : l)                {                        cout << e << endl;                }                cout << endl;                list<int> l1(l);                for (auto e : l1)                {                        cout << e << endl;                }                cout << endl;                list<int>::iterator it = l1.begin();                *it = 0;                for (auto e : l)                {                        cout << e << endl;                }                cout << endl;                for (auto e : l1)                {                        cout << e << endl;                }                cout << endl;        }        //operator=测试        void test5()        {                list<int> l({ 1,2,3,4,5 });                list<int> l1 = { 1,2,3,4,6 };                l1 = l;                for (const auto& e : l)                {                        cout << e << endl;                }                cout << endl;                for (const auto& e : l1)                {                        cout << e << endl;                }                cout << endl;                list<int>::iterator it = l1.begin();                *it = 0;                for (const auto& e : l)                {                        cout << e << endl;                }                cout << endl;                for (const auto& e : l1)                {                        cout << e << endl;                }                cout << endl;        }    //反向迭代器测试        void test6()        {                list<int> l({ 1,2,3,4,5 });                list<int>::iterator it = l.begin();                while (it != l.end())                {                        cout << *it << endl;                        ++it;                }                list<int> l2({ 1,2,3,4,5 });                list<int>::reverse_iterator it1 = l2.rbegin();                while (it1 != l2.rend())                {                        cout << *it1 << endl;                        ++it1;                }        }}
复制代码
3. list与vector的对比

vector与list都是STL中非常重要的序列式容器,由于两个容器的底层结构差别,导致其特性以及应用场景不 同,其主要差别如下:

 下次再见~~很高兴帮助到你~~

如果有问题欢迎指正批评~~


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

tsx81429

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表