<list> 是 C++ 标准模板库(STL)中的一个序列容器,它允许在容器的任意位置快速插入和删除元素。与数组或向量(<vector>)不同,<list> 不需要在创建时指定大小,并且可以在任何位置添加或删除元素,而不需要重新分配内存。常用于存储元素集合,支持双向迭代

std::list 是 C++ 标准库对 “双向链表” 这一抽象数据结构的标准化实现,而 “链表” 是更通用的概念(包含单向链表、双向链表、循环链表等多种形式)。

语法

以下是 <list> 容器的一些基本操作:与前面是类似

  • 包含头文件:#include <list>
  • 声明列表:std::list<T> mylist;,其中 T 是存储在列表中的元素类型。
  • 插入元素:mylist.push_back(value);
  • 删除元素:mylist.pop_back(); 或 mylist.erase(iterator);
  • 访问元素:mylist.front(); 和 mylist.back();
  • 遍历列表:使用迭代器 for (auto it = mylist.begin(); it != mylist.end(); ++it)

特点

  • 双向迭代<list> 提供了双向迭代器,可以向前和向后遍历元素。
  • 动态大小:与数组不同,<list> 的大小可以动态变化,不需要预先分配固定大小的内存。
  • 快速插入和删除:可以在列表的任何位置快速插入或删除元素,而不需要像向量那样移动大量元素。

声明与初始化

<list> 的声明和初始化与其他容器类似:

#include <iostream>
#include <list>

int main() {
    std::list<int> lst1;                  // 空的list
    std::list<int> lst2(5);               // 包含5个默认初始化元素的list
    std::list<int> lst3(5, 10);           // 包含5个元素,每个元素为10
    std::list<int> lst4 = {1, 2, 3, 4};   // 使用初始化列表

    return 0;
}

实例

1、基本操作

#include <iostream>
#include <list>

int main() {
    
    std::list<int> mylist = {10, 20, 30};
    // 插入和删除元素
    mylist.push_front(5);   // 头部插入
    mylist.push_back(1);    // 尾部插入
    mylist.pop_front();     // 删除头部元素
    mylist.pop_back();      // 删除尾部元素

    // 输出链表内容
    std::cout << "List elements: ";
    for (const auto& elem : mylist)
    {
        std::cout << elem << " ";
    }
    std::cout << std::endl;

    return 0;
}

2、插入和删除特定位置的元素

std::advance 是 C++ 标准库中的一个函数,它用于改变给定迭代器的位置。这个函数接受两个参数:一个迭代器和一个距离值。根据迭代器的类型和距离值的正负,std::advance 可以将迭代器向前或向后移动指定的位置数。

#include <iostream>
#include <list>

int main() {
    
    std::list<int> mylist = {1, 2, 3, 4, 5};
    auto it = mylist.begin();
    std::advance(it, 2); //移动迭代第到第三个元素

    mylist.insert(it,10);   // 在第3个元素前插入10
    mylist.erase(it);       // 删除第3个元素
   
    // 输出链表内容
    std::cout << "List elements: ";
    for (const auto& elem : mylist) {
        std::cout << elem << " ";
    }
    std::cout << std::endl;

    return 0;
}

3、排序和去重


int main() {
    
    std::list<int> mylist = { 3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5 };
    mylist.sort();          // 排序
    mylist.unique();         // 删除相邻重复元素

   
    // 输出链表内容
    std::cout << "List elements: ";
    for (const auto& elem : mylist) {
        std::cout << elem << " ";
    }
    std::cout << std::endl;

    return 0;
}

4、合并和反转

#include <iostream>
#include <list>

int main() {
    std::list<int> lst1 = {1, 3, 5, 7};
    std::list<int> lst2 = {2, 4, 6, 8};

    lst1.merge(lst2);              // 合并两个已排序的链表
    lst1.reverse();                // 反转链表

    // 输出链表内容
    std::cout << "Merged and reversed list: ";
    for (const auto& elem : lst1) {
        std::cout << elem << " ";
    }
    std::cout << std::endl;

    return 0;
}

对list::merge()的相关介绍,令我有点迷糊,查了一下资料

merge()的作用就是将两个list合并在一起,函数有2个版本:

会出现两种情况:

如果未在参数中传递比较器,则将两个排序列表合并为一个。

如果在参数中传递了比较器,则列表将根据它们的内部比较进行合并。

c1.merge(c2)------------->这个版本含糊,将c2合入c1中,但合并后元素是怎么排序的呢?
c1.merge(c2, compare)--------->这个版本比较简单,就是将c2的内容合入到c1中,然后按compare比较排序

compare: 它是一个比较函数对象,将第一个参数的值与第二个参数的值进行比较。如果第一个参数的值小于第二个参数,则返回 true,否则返回 false。

std::list::merge() 是一个 “专门为已排序链表设计的合并函数”,它要求两个输入链表必须是 “按相同排序规则排好序的”(默认是升序,即 std::less<int>)。如果输入链表未排序,merge() 的结果会是混乱的(比如 lst1={3,1}lst2={4,2},合并后不会自动排序)。

Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐