当前位置: 首页 > news >正文

【C++】list 容器操作

0. 官方文档

https://cplusplus.com/r eference/list/list/?kw=list

1. list 介绍

list 就是为了解决 vector 的缺陷出现的。

vector 缺陷:

  1. 头部和中部的插入删除效率低。O(N),因为需要挪动数据。

  2. 插入数据空间不够需要增容,增容需要开新空间,拷贝数据,释放旧空间,会付出很大代价。

list 优点:

  1. list 头部、中间插入不再需要挪动数据,效率高。O(1)

  2. list 插入数据是新增节点,不需要扩容。

list 缺点:

  1. 不支持随机访问。

所以实际使用中 vector 和 list 是相辅相成的两个容器。

2. list 的迭代器

从支持的操作接口的角度分迭代器的类型:

  • 单向(forward_list)

  • 双向(list)

  • 随机(vector)

从使用的场景的角度分迭代器的类型:

  • 正向迭代器

  • 反向迭代器

  • const迭代器

【注意】

  1. begin与end为正向迭代器,对迭代器执行++操作,迭代器向后移动

  2. rbegin与rend为反向迭代器,对迭代器执行++操作,迭代器向前移动

迭代器的使用

正向、反向、const 迭代器

/* 迭代器 */
void test_list1()
{list<int> lt1;lt1.push_back(1);lt1.push_back(2);lt1.push_back(3);lt1.push_back(4);lt1.push_front(0);lt1.push_front(-1);lt1.push_front(-2);lt1.push_front(-3);// 正向普通迭代器遍历list<int>::iterator it1 = lt1.begin();while (it1 != lt1.end()){cout << *it1 << " ";++it1;}cout << endl;list<int> lt2(lt1);        // 拷贝构造print_list(lt2);        // const 迭代器list<int> lt3;lt3.push_back(10);lt3.push_back(20);lt3.push_back(30);lt3.push_back(40);lt1 = lt3;// 只要一个容器支持迭代器,旧可以使用范围for的操作for (auto e : lt1){cout << e << " ";}cout << endl;// 反向迭代器list<int>::reverse_iterator rit = lt1.rbegin();while (rit != lt1.rend()){cout << *rit << " ";++rit;}cout << endl;
}

头插头删,尾插尾删

/* 头插头删,尾插尾删 */
void test_list2()
{// 头插与尾插list<int> lt1;lt1.push_back(1);lt1.push_back(2);lt1.push_front(0);lt1.push_front(-1);print_list(lt1);// 尾删lt1.pop_back();// 头删lt1.pop_front();print_list(lt1);
}

任意位置的插入删除

/* 任意位置的插入删除 */
void test_list3()
{list<int> lt1;lt1.push_back(1);lt1.push_back(2);lt1.push_back(3);lt1.push_back(4);print_list(lt1);// find 函数的查找范围是左闭右开的,[first, last)list<int>::iterator pos = find(lt1.begin(), lt1.end(), 3);if (pos != lt1.end())        // 一定要判断,不然找不到会直接尾插{lt1.insert(pos, 30);        // 在 3 的前面插入// 与vector不同,这里的 insert 并不会使 pos 迭代器失效lt1.erase(pos);        // 删除 3}print_list(lt1);
}

链表排序(不实用,不推荐)

/* 链表排序(不实用,不建议) */
void test_list4()
{list<int> lt1;lt1.push_back(4);lt1.push_back(2);lt1.push_back(5);lt1.push_back(1);lt1.sort();        // 排序for (auto e : lt1){cout << e << " ";}cout << endl;lt1.reverse();        // 逆置for (auto e : lt1){cout << e << " ";}cout << endl;
}

erase 导致迭代器失效问题

void test_list5()
{list<int> lt1;lt1.push_back(4);lt1.push_back(2);lt1.push_back(5);lt1.push_back(1);lt1.push_back(6);lt1.push_back(3);// 删除其中所有偶数list<int>::iterator it = lt1.begin();while (it != lt1.end()){if (*it % 2 == 0){lt1.erase(it);        // 删除后 it 迭代器失效}// 无法++,会报错无法进行递加操作++it;}print_list(lt1);
}

修改一下关键代码:

// 删除其中所有偶数
list<int>::iterator it = lt1.begin();
while (it != lt1.end())
{if (*it % 2 == 0){it = lt1.erase(it);        }else{++it;}
}

迭代器源码实现(简化版本)

下图中上半部分是 vector 的迭代器,下半部分是 list 的迭代器。

        vector 是一段连续的空间,所以可以直接把迭代器定义为类型的指针:

typedef T value_type;
typedef value_type* iterator;

        当我们 ++iterator 时,迭代器可以直接往下走到下一个元素。

        但是链表是非连续空间,是由一个个节点链接而成的,如果我们需要++迭代器来获得链表中的下一个元素,就不能简单把迭代器定义为类型的指针。要解决这个问题,我们可以用一个类型去封装节点的指针构成一个自定义类型,然后重载*、++等运算符,就可以达到我们想要的效果。


文章转载自:

http://Et9F8Wvr.ppwdh.cn
http://Z0tgghOl.ppwdh.cn
http://D0zOvg45.ppwdh.cn
http://ziDMPMBh.ppwdh.cn
http://tubo8Gp3.ppwdh.cn
http://hXfSnEz0.ppwdh.cn
http://0a5rhsit.ppwdh.cn
http://OAfD4hEo.ppwdh.cn
http://T598ocgy.ppwdh.cn
http://JyJcVaKS.ppwdh.cn
http://uLHPLKQv.ppwdh.cn
http://5LhiI7u3.ppwdh.cn
http://azsmQZb8.ppwdh.cn
http://bPBrUxbx.ppwdh.cn
http://vQrS3NQg.ppwdh.cn
http://f25ajOnm.ppwdh.cn
http://SF26U20N.ppwdh.cn
http://iwAp8oUh.ppwdh.cn
http://HXc2NtXm.ppwdh.cn
http://FzeH6vpn.ppwdh.cn
http://2IoYO5Iy.ppwdh.cn
http://ON2Nte2W.ppwdh.cn
http://gqLINbcJ.ppwdh.cn
http://FhBu88CX.ppwdh.cn
http://scthEHiw.ppwdh.cn
http://Znw2G4Mi.ppwdh.cn
http://Rczpq2a8.ppwdh.cn
http://DZ8LdgKy.ppwdh.cn
http://XEwTdilh.ppwdh.cn
http://M42UFK7v.ppwdh.cn
http://www.dtcms.com/a/374945.html

相关文章:

  • 【WRF-VPRM 预处理器第二期】VPRMpreproc.r 脚本详解
  • 430章:Python Web爬虫入门:使用Requests和BeautifulSoup
  • 在 Vite 中,环境变量的处理方式与传统的 Node.js 环境有所不同
  • 不同射频对应不同mac地址(查找无线用户连接AP信息)
  • 《红色脉络:一部PLMN在中国的演进史诗 (1G-6G)》 第9篇 | 5G:领跑者的姿态——SA/NSA之争与中国的战略选择
  • 36页可编辑PPT | 某制造集团灯塔工厂解决方案
  • 基于springboot+vue的厨艺交流平台的设计与实现(源码+论文+部署+安装)
  • 【华为OD】5G网络建设
  • 使用LLM(Ollama部署)为Bertopic确定的主题命名
  • C++容器:list
  • PAT 1178 File Path
  • ESP32开发:ubuntu22.04 下esp-idf开发环境搭建
  • JWT全面理解
  • C++:类和对象
  • Linux(3)|入门的开始:Linux基本指令(3)
  • REST接口幂等设计深度解析
  • 在Word和WPS文字中便捷切换英文段落大小写
  • 【华为OD】寻找连续区间
  • 渗透测试信息收集步骤与工具详解
  • #C语言——刷题攻略:牛客编程入门训练(十):攻克 循环控制(二),轻松拿捏!
  • 乐吾乐大屏可视化组态软件【SQL数据源】
  • 打工人日报#20250909
  • PyTorch中的flatten操作详解:从start_dim=1说起
  • 上网行为审计软件应该如何选择?适配图书馆管理的上网行为审计软件推荐
  • 计算机网络第五章(1)——传输层(概念 + UDP)
  • AI 时代,我们是否应该重温极限编程?
  • Protobuf 新版“调试表示为什么有链接?为什么会打码?我该怎么改代码?
  • php 使用html 生成pdf word wkhtmltopdf 系列1
  • vcsa6.0 升级6.7
  • python中的深拷贝与浅拷贝详细介绍