STL源码学习系列八: 序列式容器( List)

本文详细探讨了STL中的List容器,它是一个循环双向链表,内存效率较高。List容器的迭代器是双向的,适用于频繁的插入和删除操作,而不像Vector那样可能导致迭代器失效。此外,文章还介绍了List的节点结构、构造与析构、成员函数,包括insert、erase、transfer、splice、merge和sort等,并通过实例分析了这些操作的工作原理。
摘要由CSDN通过智能技术生成

序列式容器( List)


前言

在SGI STL中,list容器是一个循环的双向链表,它的内存空间效率较前文介绍的vector容器高。相对于 vector 的连续线性空间,list 就显得复杂许多,他的好处是每次插入和删除一个元素,就配置和释放一个元素空间。因此,list 对于空间的运用有绝对的精准,一点也不浪费。而且,对于任何位置的元素插入或元素移除,list 永远是常数时间。

与vector容器不同的是,list容器在进行插入操作或拼接操作时,迭代器并不会失效;且不能以普通指针作为迭代器,因为普通指针的+或-操作只能指向连续空间的后移地址或前移个地址,不能保证指向list的下一个节点,迭代器必须是双向迭代器,因为list容器具备有前移和后移的能力。

list 和 vector 是两个最常被使用的容器 , 什么时机最适合使用哪种容器 , 必须视元素的多寡,元素的构造 复杂度 ( 有无 non-trivial copy constructor, non-tirivial copy assigiunen operator) 、元素存取行为的特性而定。


list节点和list数据结构

在list容器中,list本身和list节点是分开设计的,list节点结构是存储数据和指向相邻节点的指针;如下源码所示:

template<class T>
struct _list_node
{
    typedef _list_node* void_pointer;
    void_pointer prev; //指向直接前驱节点  
    void_pointer next; //指向直接后继节点  
    T data; //节点存储的数据  
};

list本身的数据结构是只有一个指向链表节点的指针,因为list容器是循环双向链表,则足够遍历整个链表;如下源码所示:

//以下是双向链表list类的定义,分配器_Alloc默认为第二级配置器  
template <class T, class Alloc = alloc>
class list
{
    protected:
        typedef _list_node<T> list_node;

    public:
        typedef list_node* link_type;

    protected:
            link_type node; //list是一个环状双向链表,一个指针即可表示整个环状双向链表,指向尾端的空白节点
            ...
};

下面给出list节点和list本身的数据结构图:
这里写图片描述


list容器的迭代器

list容器的内存空间存储不一定是连续的,则不能用普通指针做为迭代器;list的迭代器要能够指向list的节点,并且可以进行正确的递增、递减、取值和成员存取等操作。所以迭代器要有前移、后退的能力,所以list的迭代器为双向迭代器。

这也是导致list容器的排序成员函数sort()不能使用STL算法中的排序函数,因为STL中的排序算法接受的迭代器是随机访问迭代器;

list容器在进行插入和拼接操作时迭代器不会失效;以下是源码对迭代器的定义:

#include "listNode.h"
#include "iterator.h"

namespace EasySTL
{
    //迭代器本身不是指针,因为List不是连续的区间
    template<class T,class Ref,class Ptr>
    struct _list_iterator
    {
        typedef _list_iterator<T,T&,T*> iterator; //指向内部元素值的迭代器
        typedef _list_iterator<T,Ref,Ptr> self;   //指向List节点的迭代器
        typedef bidirectional_iterator_tag iterator_category;
        typedef T value_type;
        typedef Ptr pointer;
        typedef Ref reference;
        typedef _list_node<T>* link_type;
        typedef size_t size_type;
        typedef ptrdiff_t difference_type;

        link_type node;  //普通指针指向节点

        //constructor
        _list_iterator(link_type x):node(x){}
        _list_iterator(){}
        _list_iterator(const iterator& x):node(x.node){}

        bool operator==(const self& x) const {
  return node==x.node;}
        bool operator!=(const self& x) const {
  return node!=x.node;}

        //dereference 迭代器的取值,取的是节点的数据值
        reference operator*() const {
  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值