c++STL中的list


list

list支持任意位置以O(1)的时间复杂度进行插入和删除,list的底层是一个双向带头循环链表。

list与vector的比较

  • list与vector都支持insert和erase,list在任意位置插入删除时间复杂度都是O(1).vector只有在尾部插入删除时间复杂度是O(1),在其他位置插入删除时间复杂度是O(N)
  • list提供了push_back,push_front,pop_back,pop_front的接口,而vector提供了push_back和pop_back的接口,没有提供push_front和pop_front的接口,因为vector的pop_front和push_front时间复杂度是O(N)效率太低
  • list和vector都提供了insert和erase,list的insert和erase时间复杂度是O(1),vector的insert和erase在一般位置时间复杂度是O(N).
  • list底层在物理空间上是不连续的,vector底层在物理空间上是连续的。
  • vector支持使用下标和[]进行访问,list只能使用迭代器访问,因为它的底层是一个个节点链接起来的,物理空间不连续
  • vector没有提供内置的排序函数,因为vector可以直接使用algorithm里面的sort。list提供了内置的排序函数,list::sort底层是使用的归并排序的非递归,但是list::sort效率很低,一般需要排序不会使用list结构。list不能使用algorithm里面的sort,std::sort底层使用的快排,只适用于连续的物理空间,例如vector和string.
  • vector的迭代器是原生指针,原生指针的功能在vector里面就够用。list的迭代器是一个自定义类型的类,类里面的成员变量是指向结点的指针,在类里面重载了operator*,operator->,operator!=,operator==等操作,让自定义类型的迭代器可以像指针一样进行操作。

list的迭代器

  1. list的迭代器是一个自定义类型的结构体,只有一个成员变量node*,是指向结点的指针,有多个重载的成员函数,用于控制迭代器的行为,能够让迭代器像原生指针一样使用。

  2. 自定义类型的结构体不能直接使用运算符,但是list_iterator里面的成员变量pnode是可以直接使用运算符的。虽然list_iterator里面只有一个成员变量,但它依然是一个自定义类型,不是指针类型,不能把list_iterator和指针等价

  3. 由于node是一个模板,list_iterator里面的成员变量是node<T>*,所以list_iterator也必须是一个模板。

  4. list_iterator有三个模板,template<class T,class Ref,class Ptr>,通过将这3个模板进行不同的实例化可以让list_iterator这个模板类实例化出不同行为的迭代器。

  5. typedef list_iterator<T,const T&,const T*> const_iterator,typedef list_iterator<T,T&,T*> iterator.const_iterator和iterator是一个类模板实例化出来的2个不同的类。它们的成员变量是一样的类型,但是成员函数不一样。

  6. Ref operator*() const
    {
    	return pnode->data;
    }
    

    当Ref时const T&时,对应const_iterator.Ref为T&,对应iterator。普通迭代器和const迭代器都是普通属性的迭代器,可以调用普通成员函数和const成员函数。const const_iterator和const iterator是const属性的迭代器,只能调用const成员函数。

  7. 成员函数后面的const修饰的是*this,表示成员变量pnode不能改变,但是pnode指向的内容可以改变。在operator*()后面可以加const,普通属性的迭代器也可以调用,而且也能返回T&。const const_iterator和const iterator都能调用operator*(),const const_iterator调用operator*()const返回的是const T&,const iterator调用operator*()const返回的是T&

  8. operator*() 对于const属性的迭代器和非const属性的迭代器都能调用,const属性的迭代器和非const属性的迭代器区别是它们的成员变量pnode能否被直接修改。

  9. 普通list对象使用普通迭代器,普通迭代器可以实现对成员变量的读写操作。

  10. const修饰的list对象使用const_iterator,const_iterator也能++和–,const_iterator++和–返回的是const_iterator。iterator的++和–返回iterator,它们是2个不同的类

  11. 通过模板实例化能控制list_iterator的行为。让其表现出iterator和const_iterator的效果。

  12. const list<int> l,l中pnode不能修改,但是pnode指向的对象可以被修改

  13. const修饰list<int> l,l的成员变量不能直接被修改,l也不能调用普通成员函数。

模拟实现

#pragma once
#include <iostream>
#include <assert.h>
namespace slowstep
{
    template <typename T>
    struct list_node
    {
        //list_node的默认构造
        list_node(const T &d = T()) : data(d), next(nullptr), prev(nullptr) {}
        //成员变量
        list_node<T> *next;
        list_node<T> *prev;
        T data;
    };
    template <class T, class Ref, class Ptr>
    struct list_iterator
    {
        typedef list_node<T> node;
        typedef list_iterator<T, Ref, Ptr> iterator;
        //成员变量
        node *pnode;
        //通过节点的指针构造
        list_iterator(node *p) : pnode(p) {}
        //特殊构造函数
        list_iterator(const list_iterator<T,T&,T*>& it):pnode(it.node){}
        list_iterator(const list_iterator<T,const T&,const T*>& it):pnode(it.node){}
        /*
        这2个构造函数可以用普通迭代器构造const迭代器,也能用const迭代器构造普通迭代器.
        */
        Ref operator*() const
        {
            return pnode->data;
        }
        //当list里面存放结构体时,可以使用迭代器+一个箭头访问就结构体成员.编译器做了特殊处理隐藏了一个箭头
        Ptr operator->() const
        {
            return &(pnode->data);
        }
        bool operator==(const iterator &it) const
        {
            return it.pnode == pnode;
        }
        bool operator!=(const iterator &it) const
        {
            return it.pnode != pnode;
        }
        iterator &operator++()
        {
            pnode = pnode->next;
            return *this;
        }
        iterator operator++(int)
        {
            iterator tmp = *this;
            pnode = pnode->next;
            return tmp;
        }
        iterator &operator--()
        {
            pnode = pnode->prev;
            return *this;
        }
        iterator operator--(int)
        {
            iterator tmp = *this;
            pnode = pnode->prev;
            return tmp;
        }
    };
    template <class T>
    class list
    {
        typedef list_node<T> node;
    public:
        typedef list_iterator<T, T &, T *> iterator;//普通迭代器
        typedef list_iterator<T, const T &, const T *> const_iterator;//const迭代器
        list()
        {
            _head = new node;
            _head->next = _head;
            _head->prev = _head;
        }
        list(size_t n, const T &val = T())
        {
            _head = new node;
            _head->next = _head;
            _head->prev = _head;
            while (n--)
                push_back(val);
        }
        list(int n, const T &val = T())
        {
            _head = new node;
            _head->next = _head;
            _head->prev = _head;
            while (n--)
                push_back(val);
        }
        template <class Inputiterator>//迭代器区间的构造函数使用模板,支持泛型
        list(Inputiterator first, Inputiterator last)
        {
            _head = new node;
            _head->next = _head;
            _head->prev = _head;
            while (first != last)
            {
                push_back(*first);
                first++;
            }
        }
        list(const list<T> &l) : _head(nullptr)//拷贝构造
        {
            _head = new node;
            _head->next = _head;
            _head->prev = _head;
            list<T> tmp(l.begin(), l.end());
            std::swap(tmp._head, _head);
        }
        list<T> &operator=(const list<T> &l)
        {
            list<T> tmp(l);
            std::swap(tmp._head, _head);
            return *this;
        }
        iterator begin()
        {
            return iterator(_head->next);
        }
        iterator end()
        {
            return iterator(_head);
        }
        const_iterator begin() const
        {
            return const_iterator(_head->next);
        }
        const_iterator end() const
        {
            return const_iterator(_head);
        }
        iterator insert(const iterator &pos, const T &val)
        {
            node *prev = pos.pnode->prev;
            node *newnode = new node(val);
            prev->next = newnode;
            newnode->prev = prev;
            newnode->next = pos.pnode;
            pos.pnode->prev = newnode;
            return iterator(newnode);
        }
        iterator erase(const iterator &pos)
        {
            assert(pos.pnode != _head);
            node *prev = pos.pnode->prev;
            node *next = pos.pnode->next;
            delete pos.pnode;
            prev->next = next;
            next->prev = prev;
            return iterator(next);
        }
        void push_back(const T &val)
        {
            insert(iterator(_head), val);
        }
        void push_front(const T &val)
        {
            insert(iterator(_head->next), val);
        }
        void pop_back()
        {
            erase(iterator(_head->prev));
        }
        void pop_front()
        {
            erase(iterator(_head->next));
        }
        const T &front() const
        {
            return _head->next->data;
        }
        T &front()
        {
            return _head->next->data;
        }
        const T &back() const
        {
            return _head->prev->data;
        }
        T &back()
        {
            return _head->prev->data;
        }
        bool empty() const
        {
            return _head->next == _head;
        }
        size_t size() const
        {
            size_t ans = 0;
            const_iterator it = begin();
            while (it != end())
            {
                ans++;
                it++;
            }
            return ans;
        }
        void swap(list<T> &l)
        {
            std::swap(_head, l._head);
        }
        void clear()
        {
            if (_head->next == _head)
                return;
            node *prev = _head->next;
            node *cur = prev->next;
            while (cur != _head)
            {
                delete prev;
                prev = cur;
                cur = cur->next;
            }
            delete prev;
            _head->next = _head;
            _head->prev = _head;
        }
        void reverse()
        {
            node *l = _head->next;
            node *r = _head->prev;
            while (l != r && l->next != r)
            {
                std::swap(l->data, r->data);
                l = l->next;
                r = r->prev;
            }
            if (l->next == r)
                std::swap(l->data, r->data);
        }
        void remove(const T &val)
        {
            iterator it = begin();
            while (it != end())
            {
                if (*it == val)
                    it = erase(it);
                else
                    it++;
            }
        }
        ~list()
        {
            clear();
            delete _head;
            _head = nullptr;
        }
    private:
        node *_head;
    };
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值