【STL】list

list源码实现

G2.9版本的list源码

list底层实现为双向循环链表,并且环状链表的尾端还有一个空白节点,代表尾后迭代器指向的节点,用以符合STL前闭后开的原则,其示意图如下:
在这里插入图片描述

  • list代表一个双向链表,__list_node代表链表中每一个节点,__list_iterator代表每一个节点的迭代器
  • list中存在一个__list_node*类型的节点指针begin()和end()分别指向list的头部节点和尾部节点,另外尾部节点不赋值,头部节点赋值,以满足list前闭后开的特性
  • __list_node中的指针类型未void*,之后在使用的时候需要进行转换
  • list的初始化大小为4个字节,因为它只有一个__list_node*类型的node

G4.9版本的list源码

在这里插入图片描述

  • list代表一个双向链表,list继承于_List_base,且_List_base包含_List_impl,_List_impl继承于_A,即利用内存管理保存_List_node(_List_node相当于一个节点,继承于_List_node_base,保存了前后指针和data),同时保存了变量_M_node
  • list中存在一个_List_node_base*类型的节点指针begin()和end()分别指向list的头部节点和尾部节点,另外尾部节点不赋值,头部节点赋值,以满足list前闭后开的特性
  • list的初始化大小为8个字节,因为它只有一个_List_node_base类型的变量_M_node,而该变量由两个指针构成

G4.9和G2.9源码比较

在这里插入图片描述

list中的iterator的设计

template <class T, class Ref, class Ptr>
struct __list_iterator{
    typedef __list_iterator<T, Ref, Ptr>  self;
    typedef bidirectional_iterator_tag    iterator_category;
    typedef T                             value_type;
    typedef Ptr                           pointer;
    typedef Ref                           reference;
    typedef __list_node<T>*               link_type;
    typedef ptrdiff_t                     difference_type;
 
    link_node node;
    
    reference operator*() const { return (*node).data; }
    pointer operator->() const { return &(operator*()); }
    self& operator++()
        { node = (link_type)((*node).next); return *this; }
    self operator++(int)
        { self tmp = *this; ++*this; return tmp; }
    
    ......
};

在这里插入图片描述

  • 从 self tmp = *this; 这个语句来看有两种执行方案,
    1. this可以先调用operator*(),再调用=,
    2. 先将this指针转化为变量,再调用operator=(),
    但是operator*()和operator=()的返回值不同,通过同时尝试两种不同的情况就会发现,方案2是可行的
  • 另外需要考虑prefix和profix返回值的情况,由于连续两次后++不被允许,而连续两次前++被允许,所以prefix返回引用型,postfix返回普通变量型
    在这里插入图片描述
    详情请参考【C++の相关概念】operator->重载

注意事项

list为何不能使用::sort()进行排序

template <class RandomAccessIterator>
inline void sort(RandomAccessIterator first, RandomAccessIterator last){
    if(first != last){
        __introsort_loop(first, last, value_type(first), __lg(last - first) * 2);
        __final_insertion_sort(first, last);
    }
}
 
template <class RandomAccessIterator, class T, class Size>
void __introsort_loop(RandomAccessIterator first,
                      RandomAccessIterator last,
                      T*,
                      Size depth_limit){
......
    RandomAccessIterator cut = __unguarded_partition
        (first, last, T(__median(*first, *(first + (last - first)/2), *(last - 1))));
......
}

通过阅读以上::sort()源码发现,:sort()支持的迭代器是随机访问迭代器,而list中的迭代器不是随机访问迭代器,所以也就不提供这个操作。这样设计是合理的,因为list是链表,无法在线性时间内得到递增或递减k次的结果。

list的迭代器类型以及相关操作的时间复杂度
双向迭代器
list为可反转容器
不支持随机访问元素
末尾插入删除元素 常量时间
中间或开头删插元素 常量时间
list的迭代器失效问题
增加任何元素都不会使迭代器失效。删除元素时,除了指向当前被删除元素的迭代器外,其它迭代器都不会失效。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
STL list是C++标准模板库中的一个双向链表容器,它提供了一系列接口用于操作和管理链表中的元素。下面是一些常见的STL list接口: 1. 构造函数: - list(size_type n, const value_type& val = value_type()):构造包含n个值为val的元素的list。 - list():构造一个空的list。 - list(const list& x):拷贝构造函数,用于复制另一个list的内容构造新的list。 - list(InputIterator first, InputIterator last):用[first, last)区间中的元素构造list。 2. 容器大小: - size():返回list中元素的个数。 - empty():检查list是否为空。 3. 元素访问: - front():返回list中第一个元素的引用。 - back():返回list中最后一个元素的引用。 4. 插入和删除元素: - push_front(const value_type& val):在list的开头插入一个元素。 - pop_front():移除list的第一个元素。 - push_back(const value_type& val):在list的末尾插入一个元素。 - pop_back():移除list的最后一个元素。 - insert(iterator position, const value_type& val):在指定位置之前插入一个元素。 - erase(iterator position):移除指定位置的元素。 - erase(iterator first, iterator last):移除[first, last)区间中的元素。 5. 元素操作: - clear():移除list中的所有元素。 - remove(const value_type& val):移除所有等于val的元素。 - unique():移除所有相邻重复的元素。 - sort():对list中的元素进行排序。 - reverse():反转list中元素的顺序。 你可以参考C++官方文档(https://cplusplus.com/reference/list/list/)了解更多关于STL list的接口和用法。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值