• 【C++ STL】-- list介绍与使用


    目录

    前言

    list的介绍

    list结构图

    list的定义方式

    list成员函数

    迭代器的使用

    begin、end、rbegin、rend

    const修饰的迭代器

    范围for

    容量操作

    empty、size

    列表元素访问

    front、back

    列表修饰符

    push_back、pop_back、push_front、pop_front

    insert、erase 

    swap、clear

    resize

    操作函数

    splice

    remove、remove_if

    sort、unique

    merge

    reverse


    前言

            相较于vector的连续线性空间,list就显得复杂的许多,它的好处就是每次插入与删除一个元素的时候,只需要配置或释放一个空间即可。因此,list对于空间的运用有绝对的精准,一点也不会浪费。而且对于任何位置的元素插入或元素删除,list永远是常数。

    list的介绍

    list的文档介绍

             list是可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代。 list的底层是双向链表结构,双向链表中每个元素存储在互不相关的独立节点中,在节点中通过指针指向其前一个元素和后一个元素。

    list结构图

            STL list 容器,又称双向链表容器,即该容器的底层是以双向链表的形式实现的。list 容器中的元素可以分散存储在内存空间里,而不是存储在一整块连续的内存空间中。

    list的定义方式

    方式一:规定的存储类型的空容器

    1. //int类型
    2. list<int> lt1;
    3. //double类型
    4. list<double lt2;

    方式二:利用其他容器的迭代器构造

    1. vector<int> v{1, 2, 3, 4, 5};
    2. list<int> lt(v.begin(), v.end());

    方式三:构造为含有n个val

    1. //5个1
    2. list<int> lt2(5, 1);

    方式四:以另一个list容器构造

    1. list<int> lt1(5, 1);
    2. list<int> lt2(lt1);

    方式五:列表格式初始化C++11 

    list<int> lt{ 1,2,3,4,5 };

    方式六:以数组为迭代器区间构造

    1. int array[] = { 16,2,77,29 };
    2. list<int> lt(array, array + sizeof(array) / sizeof(int));

    list成员函数

    迭代器的使用

            将迭代器理解成一个指针,该指针指向list中的某个节点。

    函数声明
    接口说明
    begin  
    end
    返回第一个元素的迭代器+返回最后一个元素下一个位置的迭代器
    rbegin  
    rend
    返回第一个元素的 reverse_iterator, end 位置 返回最后一个元素下一个位置的
    reverse_iterator, begin 位置
    注意: . (遍历链表只能用迭代器和范围for)
    • begin与end为正向迭代器,对迭代器执行++操作,迭代器向后移动
    • rbegin(end)与rend(begin)为反向迭代器,对迭代器执行++操作,迭代器向前移动

    begin、end、rbegin、rend

    1. #include
    2. #include
    3. #include
    4. using namespace std;
    5. int main(){
    6. int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
    7. list<int> lt(array, array + sizeof(array) / sizeof(array[0]));
    8. // 使用正向迭代器正向list中的元素
    9. // list::iterator it = l.begin(); // C++98中语法
    10. auto it = lt.begin(); // C++11之后推荐写法
    11. while (it != lt.end())
    12. {
    13. cout << *it << " ";
    14. ++it;
    15. }
    16. cout << endl;
    17. // 使用反向迭代器逆向打印list中的元素
    18. // list::reverse_iterator rit = lt.rbegin(); // C++98中语法
    19. auto rit = lt.rbegin(); // C++11之后推荐写法
    20. while (rit != lt.rend())
    21. {
    22. cout << *rit << " ";
    23. ++rit;
    24. }
    25. cout << endl;
    26. }

    const修饰的迭代器

    1. #include
    2. #include
    3. #include
    4. using namespace std;
    5. int main(){
    6. // 注意这里调用的是list的 begin() const,返回list的const_iterator对象
    7. for (list<int>::const_iterator it = l.begin(); it != l.end(); ++it)
    8. {
    9. cout << *it << " ";
    10. // *it = 10; 编译不通过
    11. }
    12. cout << endl;
    13. }

    范围for

    1. #include
    2. #include
    3. #include
    4. using namespace std;
    5. int main() {
    6. vector<int> v{ 1,2,3,4,5 };
    7. list<int> lt(v.begin(), v.end());
    8. // C++11范围for的方式遍历
    9. for (auto& e : lt)
    10. cout << e << " ";
    11. cout << endl;
    12. //输出:1 2 3 4 5
    13. return 0;
    14. }

    容量操作

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

    empty、size

    1. #include
    2. #include
    3. #include
    4. using namespace std;
    5. int main() {
    6. int array[] = { 1, 2, 3 };
    7. list<int> lt(array, array + sizeof(array) / sizeof(array[0]));
    8. cout << lt.size() << endl;//输出:3
    9. while (!lt.empty()) {
    10. cout << lt.front() << " ";
    11. lt.pop_front();
    12. }
    13. cout << endl;//输出:1 2 3
    14. cout << lt.size() << endl;//输出:0
    15. return 0;
    16. }

    列表元素访问

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

    front、back

    1. #include
    2. #include
    3. #include
    4. using namespace std;
    5. int main()
    6. {
    7. list<int> lt;
    8. lt.push_back(1);
    9. lt.push_back(2);
    10. //front与back返回的是引用,可以修改list内部数据
    11. lt.front() -= lt.back();
    12. cout << lt.front() << endl;//输出:-1
    13. lt.back() -= lt.front();
    14. cout << lt.back() << endl;//输出:3
    15. return 0;
    16. }

    列表修饰符

    函数声明
    接口说明
    push_frontlist首元素前插入值为val的元素
    pop_front删除list中第一个元素
    push_backlist尾部插入值为val的元素
    pop_back 删除list中最后一个元素
    insert在 list position 位置中插入值为val的元素
    erase
    交换两个 list中的元素
    swap 交换两个list中的元素
    clear清空list中的有效元素
    resize调整容器大小,使其包含n个元素。

    push_back、pop_back、push_front、pop_front

    1. #include
    2. #include
    3. #include
    4. using namespace std;
    5. void Print_list(list<int>& lt) {
    6. for (auto val : lt)
    7. cout << val << " ";
    8. cout << endl;
    9. }
    10. int main()
    11. {
    12. int array[] = { 1, 2, 3 };
    13. list<int> lt(array, array + sizeof(array) / sizeof(array[0]));
    14. Print_list(lt);//输出:1 2 3
    15. // 在list的尾部插入4,头部插入0
    16. lt.push_back(4);
    17. lt.push_front(0);
    18. Print_list(lt);//输出:0 1 2 3 4
    19. // 删除list尾部节点和头部节点
    20. lt.pop_back();
    21. lt.pop_front();
    22. Print_list(lt);//输出:1 2 3
    23. return 0;
    24. }

    insert、erase 

    1. #include
    2. #include
    3. #include
    4. using namespace std;
    5. int main() {
    6. int array[] = { 1, 2, 3 };
    7. list<int> lt(array, array + sizeof(array) / sizeof(array[0]));
    8. // 获取链表中第二个节点
    9. auto pos = ++lt.begin();
    10. cout << *pos << endl;
    11. // 在pos前插入值为4的元素
    12. lt.insert(pos, 4);
    13. // 在pos前插入5个值为5的元素
    14. lt.insert(pos, 5, 5);
    15. // 在pos前插入[v.begin(), v.end)区间中的元素
    16. vector<int> v{ 7, 8, 9 };
    17. lt.insert(pos, v.begin(), v.end());
    18. // 删除pos位置上的元素
    19. lt.erase(pos);
    20. // 删除list中[begin, end)区间中的元素,即删除list中的所有元素
    21. lt.erase(lt.begin(), lt.end());
    22. return 0;
    23. }

    swap、clear

    1. #include
    2. #include
    3. #include
    4. using namespace std;
    5. int main() {
    6. // 用数组来构造list
    7. int array[] = { 1, 2, 3 };
    8. list<int> lt1(array, array + sizeof(array) / sizeof(array[0]));
    9. // 交换l1和l2中的元素
    10. list<int> lt2;
    11. lt1.swap(lt2);
    12. cout << lt2.size() << endl;//输出:3
    13. // 将lt1中的元素清空
    14. lt2.clear();
    15. cout << lt2.size() << endl;//输出:0
    16. return 0;
    17. }

    resize

    • 如果n小于当前容器大小,则内容将减少到其前n个元素,并删除(并销毁)超出的元素。
    • 如果n大于当前容器大小,则通过在末尾插入尽可能多的元素来扩展内容,以达到n的大小。如果指定了val,则将新元素初始化为val,否则将对其进行值初始化(为0)。
    1. #include
    2. #include
    3. #include
    4. using namespace std;
    5. int main()
    6. {
    7. list<int> lt;
    8. for (int i = 1; i < 10; ++i)
    9. lt.push_back(i);
    10. //1 2 3 4 5 6 7 8 9
    11. lt.resize(5); //1 2 3 4 5
    12. lt.resize(8, 100); //1 2 3 4 5 100 100 100
    13. lt.resize(12); //1 2 3 4 5 100 100 100 0 0 0 0
    14. return 0;
    15. }

    操作函数

    函数声明
    接口说明
    splice将元素从列表转移到列表
    remove删除具有特定值的元素
    remove_if删除满足条件的元素
    unique删除重复值
    sort对容器中的元素排序
    merge合并排序列表
    reverse反转元素的顺序

    splice

    1. #include
    2. #include
    3. using namespace std;
    4. int main()
    5. {
    6. int array[] = { 1, 2, 3, 4 ,5 ,6 ,7 ,8 ,9 ,10 };
    7. list<int> lt1(array, array + 5);
    8. list<int> lt2(array + 5, array + 10);
    9. lt1.splice(lt1.begin(), lt2); //将容器lt2拼接到容器lt1的开头
    10. //lt1:6 7 8 9 10 1 2 3 4 5
    11. list<int> lt3(array, array + 5);
    12. list<int> lt4(array + 5, array + 10);
    13. lt3.splice(lt3.begin(), lt4, lt4.begin()); //将容器lt4的第一个数据拼接到容器lt3的开头
    14. //lt3:6 1 2 3 4 5
    15. list<int> lt5(array, array + 5);
    16. list<int> lt6(array + 5, array + 10);
    17. lt5.splice(lt5.begin(), lt6, lt6.begin(), lt6.end()); //将容器lt6的指定迭代器区间内的数据拼接到容器lt5的开头
    18. //lt5:6 7 8 9 10 1 2 3 4 5
    19. return 0;
    20. }

    remove、remove_if

    1. #include
    2. #include
    3. #include
    4. using namespace std;
    5. bool single_digit(const int& val)
    6. {
    7. return val < 5;
    8. }
    9. int main() {
    10. int array[] = { 1, 2, 3, 4, 5, 6 };
    11. list<int> lt(array, array + sizeof(array) / sizeof(array[0]));
    12. lt.remove(3); //删除容器当中值为3的元素
    13. //1 2 4 5 6
    14. lt.remove_if(single_digit); //删除容器当中值小于10的元素
    15. //5 6
    16. return 0;
    17. }

    sort、unique

    1. #include
    2. #include
    3. using namespace std;
    4. int main(){
    5. int array[] = { 3, 2, 1, 6, 5, 4, 4, 5, 6 };
    6. list<int> lt(array, array + sizeof(array) / sizeof(array[0]));
    7. lt.sort(); //将容器当中的元素排为升序
    8. //1 2 3 4 4 5 5 6 6
    9. lt.unique(); //删除容器当中连续的重复元素
    10. //1 2 3 4 5 6
    11. return 0;
    12. }

    merge

            用于将一个有序list容器合并到另一个有序list容器当中,若要实现无序排序合并建议使用splice。

    1. #include
    2. #include
    3. using namespace std;
    4. bool mycomparison(int first, int second) { return first > second; }
    5. int main()
    6. {
    7. int array1[] = { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 };
    8. list<int> lt1(array1, array1 + 5);
    9. list<int> lt2(array1+5, array1 + 10);
    10. //用于将一个有序list容器合并到另一个有序list容器当中
    11. //要求列表容器的元素在调用之前已经按comp(mycomparison)排序。否则报错
    12. //若要实现无序排序合并建议使用splice
    13. lt1.merge(lt2,mycomparison); //将lt2合并到lt1当中
    14. //lt1:1 2 3 5 6 8 9 10
    15. int array2[] = { 100, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    16. list<int> lt3(array2, array2 + 5);
    17. list<int> lt4(array2 + 5, array2 + 10);
    18. //comp默认:如果第一个参数被认为小于第二个参数,则返回true,否则返回false。
    19. lt3.merge(lt4); //error
    20. return 0;
    21. }

    reverse

    1. #include
    2. #include
    3. using namespace std;
    4. int main()
    5. {
    6. int array1[] = { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 };
    7. list<int> lt(array1, array1 + 10);
    8. //10 9 8 7 6 5 4 3 2 1
    9. lt.reverse(); //将容器当中元素的位置进行逆置
    10. //1 2 3 4 5 6 7 8 9 10
    11. return 0;
    12. }
  • 相关阅读:
    借助 ControlNet 生成艺术二维码 – 基于 Stable Diffusion 的 AI 绘画方案
    【附源码】Python计算机毕业设计美容院管理系统
    数字孪生金融网点建设方案,应用架构可视化。
    如何在 Keras 中开发具有注意力的编码器-解码器模型
    力扣:365. 水壶问题
    LeetCode算法—排序算法(以升序为例)
    Apache Ftp Server 部署,它的帐号密码加密算法是什么呢?
    HBuilder发行微信小程序
    智慧水务解决方案-最新全套文件
    日 志
  • 原文地址:https://blog.csdn.net/weixin_64609308/article/details/127583538