list的常见接口使用

今天,我们来讲解一下C++关于STL标准库中的一个容器list的常见接口。

在我们之前c语言数据结构中,我们已经了解过了关于链表的知识点了,那么对于现在理解它也是相对来说比较容易的了。

数据结构--双向循环链表-CSDN博客

1. 定义与包含头文件

  • 首先要包含 <list> 头文件才能使用 list 容器。例如: #include <list> 。

  • 定义一个 list 容器的基本语法是 std::list<数据类型> 列表名; 。

比如 std::list<int> myList; 就定义了一个存储整数的 list 容器。

2. 特点

https://cplusplus.com/reference/list/

1- 双向链表结构: list 在内部是通过双向链表实现的。这意味着每个元素(节点)都包含指向前一个元素后一个元素 的指针。这种结构使得在序列中的任何位置进行插入和删除操作都非常高效,时间复杂度为常数时间O(1),因为不需要移动其他元素,只需要调整节点间的指针。

2- 元素存储:元素在内存中不是连续存储的,与数组(如 std::vector )不同。这使得 list 可以高效地进行插入和删除操作,但随机访问元素的效率较低,访问第n个元素的时间复杂度为O(n)。

3- list与forward_list非常相似:最主要的不同在于forward_list是单链表,只能朝前迭代,已让其更简单高效。

list的接口比较多,这里也是讲解比较常用的接口,其余的到时候需要再去官网查询即可

一:list的构造

|---------------------------------------------------------------------------|---------------------------------|
| explicit 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 |

ps:解释explicit

explit:用于防止隐式转换。在没有 explicit 关键字修饰构造函数时,编译器可以使用单参数构造函数(或者除第一个参数外其余参数都有默认值的多参数构造函数)进行隐式转换。而 explicit 关键字就是用来禁止这种隐式转换的。

好处:

-可以提高代码的可读性和安全性。通过禁止隐式转换,代码的意图更加明确,减少了一些可能由于意外的隐式转换而导致的错误。同时,在需要进行类型转换时,显式的转换也能让阅读代码的人清楚地知道发生了什么操作。
其中,在vector中,我们解释了为啥要弄成val=T()? 同样在list中也是类似的!

代码演示:下面以int类型为演示,当然也可以改成string,char等等。

复制代码
void TestList1()
{

 构造空的lt1
 list<int> lt1;  

                       
 lt2中放4个值为100的元素
  list<int> lt2(4, 100); 
             

用lt2的[begin(), end())左闭右开的区间构造lt3
 list<int> lt3(lt2.begin(), lt2.end()); 

   
 用lt3拷贝构造lt4
list<int> lt4(lt3);                    



 以数组为迭代器区间构造lt5
  int array[] = { 16,2,77,29 };
  list<int> l5(array, array + sizeof(array) / sizeof(int));



   列表格式初始化C++11
   list<int> l6{ 1,2,3,4,5 };



    用迭代器方式打印lt5中的元素
    list<int>::iterator it = l5.begin();
    while (it != l5.end())
    {
        cout << *it << " ";
        ++it;
    }       
    cout << endl;



    C++11范围for的方式遍历
   for (auto& e : l5)
       cout << e << " ";

    cout << endl;
}

list iterator迭代器的使用

1.begin和end

2.rbegin和rend

我们在vector和string中知道迭代器的使用了:(其实都是一样的)

复制代码

正向迭代器:迭代器执行++操作,迭代器向后移动

反向迭代器:迭代器执行++操作,迭代器向前移动

代码演示:

**注意:***链表遍历只能使用迭代器或者范围for:因为它是不连续的*****

复制代码
void PrintList(const list<int>& l)
{
   ***注意这里调用的是list的 begin() const,返回list的const_iterator对象
    for (list<int>::const_iterator it = l.begin(); it != l.end(); ++it)
    {
        cout << *it << " ";
        // *it = 10; 编译不通过,因为const不能够修改
    }

void TestList2()
{
    int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    list<int> l(array, array + sizeof(array) / sizeof(array[0]));
    // 使用正向迭代器正向list中的元素
    // list<int>::iterator it = l.begin();   // C++98中语法
    auto it = l.begin();                     // C++11之后推荐写法
    while (it != l.end())
    {
        cout << *it << " ";
        ++it;
    }
    cout << endl;


    // 使用反向迭代器逆向打印list中的元素
    // list<int>::reverse_iterator rit = l.rbegin();
    auto rit = l.rbegin();
    while (rit != l.rend())
    {
        cout << *rit << " ";
        ++rit;
    }
    cout << endl;
}

Capacity容量:

|-------|------------------------------|
| 函数声明 | 接口说明 |
| empty | 检测list是否为空,是返回true,否则返回false |
| size | 返回list中有效节点的个数 |

Element access元素访问:

|-------|------------------------|
| 函数声明 | 接口说明 |
| front | 返回list的第一个节点中值的引用 |
| back | 返回list的最后一个节点中值的引用 |

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中的有效元素 |
| assign | 追加新的内容到list中 |

复制代码
void TestList3()
{
    int array[] = { 1, 2, 3 };
    list<int> L(array, array + sizeof(array) / sizeof(array[0]));

    // 在list的尾部插入4,头部插入0
    L.push_back(4);
    L.push_front(0);
    PrintList(L);

    // 删除list尾部节点和头部节点
    L.pop_back();
    L.pop_front();
    PrintList(L);
}

void TestList4()
{
    int array1[] = { 1, 2, 3 };
    list<int> L(array1, array1 + sizeof(array1) / sizeof(array1[0]));

    // 获取链表中第二个节点
    auto pos = ++L.begin();
    cout << *pos << endl;

    // 在pos前插入值为4的元素
    L.insert(pos, 4);
    PrintList(L);

    // 在pos前插入5个值为5的元素
    L.insert(pos, 5, 5);
    PrintList(L);

    // 在pos前插入[v.begin(), v.end)区间中的元素
    vector<int> v{ 7, 8, 9 };
    L.insert(pos, v.begin(), v.end());
    PrintList(L);

    // 删除pos位置上的元素
    L.erase(pos);
    PrintList(L);

    // 删除list中[begin, end)区间中的元素,即删除list中的所有元素
    L.erase(L.begin(), L.end());
    PrintList(L);
}

void TestList5()
{
    // 用数组来构造list
    int array1[] = { 1, 2, 3 };
    list<int> l1(array1, array1 + sizeof(array1) / sizeof(array1[0]));
    PrintList(l1);

    // 交换l1和l2中的元素
    list<int> l2;
    l1.swap(l2);
    PrintList(l1);
    PrintList(l2);

    // 将l2中的元素清空
    l2.clear();
    cout << l2.size() << endl;
}

区分迭代器的性质:

1.迭代器的性质有底层的结构决定。

我们可以看到,上面的函数模板的定义的迭代器不同,它们分别代表什么意思呢?

分别代表:

1. 单向迭代器:

  • 只能按照一个方向来遍历元素,通常是从容器的第一个元素开始,按顺序依次向后访问,不能往回走 eg:单链表

2.双向迭代器:

在单向迭代器的基础上增加了反向遍历的功能。可以向前也可以向后移动,能更灵活地访问元素。例如在处理双向链表数据结构时,双向迭代器可以方便地在链表中前后移动来查找或者操作节点。 eg:list,map(以后学),set(以后学)

3. 随机迭代器:

它的功能更强大,不仅可以像双向迭代器那样前后移动,还能够直接跳转到容器中的任意一个合法位置访问元素,就像知道每个元素的"地址"一样,可以随意访问。比如对于一个数组,随机迭代器可以直接通过索引定位并访问元素,在需要随机访问数据的场景下,如对内存中的数据块进行抽样检查,随机迭代器就能发挥优势。

eg:vector,string,deque(后面讲优先队列时讲解)

迭代器失效问题:

迭代器失效即迭代器所指向的节点的无效,即该节点被删除了。因为list的底层结构为带头结点的双向循环链表,因此在list中进行插入时是不会导致list的迭代器失效的,只有在删除时才会失效,并且失效的只是指向被删除节点的迭代器,其他迭代器不会受到影响

好了,list的常见使用接口的讲解就到这结束了,希望你我共进步!

最后,鸡汤环节:

共勉!

相关推荐
Scott9999HH1 小时前
【IIoT流量实战】蒸汽管道阀门全关却仍有流量?用 Python 实现涡街信号 FFT 频谱分析与温压全补偿积算网关,深度拆解靠谱的涡街流量计厂家硬核技术标准
开发语言·python
2401_841495642 小时前
【操作系统】进程同步与互斥实验报告
c++·算法·操作系统·进程·并发·同步·互斥
fqbqrr2 小时前
2607C++,soui与安卓
c++·soui
码智社2 小时前
AES加密原理详解及Java实现加解密实战
java·开发语言
AI云海2 小时前
python 列表、元组、集合和字典
开发语言·python
克里斯蒂亚诺更新3 小时前
ruoyi角色权限的对应关系
笔记
萧瑟余晖3 小时前
JDK 26 新特性详解
java·开发语言
马优晨4 小时前
Freemarker 完整讲解(后端 Java 模板引擎)
java·开发语言·freemarker·freemarker 完整讲解·freemarker模板引擎
a1117765 小时前
2FA 验证码生成器(github登录验证 app)
笔记·学习
fqbqrr6 小时前
2607C++,使用微软detours勾挂工具
c++