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

C++ STL-List容器概念及应用方法详解

1.链表概念

功能:将数据进行链式存储。

链表(list)是一种物理存储单元上非连续的存储结构,数据元素的逻辑顺序是通过链表中的指针链接实现的 。

链表的组成:链表由一系列结点组成 。

结点的组成:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域STL中的链表是一个双向循环链表。

由于链表的存储方式并不是连续的内存空间,因此链表list中的迭代器只支持前移和后移,属于双向迭代器。

list的优点:

  • 采用动态存储分配,不会造成内存浪费和溢出。
  • 链表执行插入和删除操作十分方便,修改指针即可,不需要移动大量元素。

list的缺点:

  • 链表灵活,但是空间(指针域) 和 时间(遍历)额外耗费较大。
  • List有一个重要的性质,插入操作和删除操作都不会造成原有list迭代器的失效,这在vector是不成立的。

2.头文件

头文件:#include<list>

3.初始化

格式为:explicit list (const allocator_type& alloc = allocator_type());

我们以int类型作为参数为例进行创建,其创建方法与vector无异

list<int> l1;           //创建一个空链表list<int> l2(10);       //创建一个链表其有10个空元素list<int> l3(5,20);     //创建一个链表其有5个元素内容为20list<int> l4(l3.begin(),l3.end());  //创建一个链表其内容为l3的内容list<int> l5(l4);               //创建一个链表其内容为l4的内容

4. 迭代器

遍历代码举例(其方法和vector版本无异只是更加精简):

list<int> li;
for(list<int>::iterator it=li.begin();it!=li.end();it++){cout<<*it<<' ';}

5. 常用接口

我们使用list<int> li;预先创建了一个链表,命名为li,方便举例

5.1 判断是否为空empty()

返回一个bool类型的值,只存在真和假,当链表为空时为真,不为空时为假

函数原型

bool empty() const;

if(li.empty()){     //当链表为空的时候执行cout<<"is empty()"<<endl;}else{cout<<"not empty()"<<endl;}

5.2 获取大小size()

返回链表元素的个数

函数原型

size_type size() const;

cout<<li.size()<<endl;

5.3 链表前插入push_front() &&删除 pop_front()

push_front()表示在链表最前端插入一个数据,pop_front()表示在链表最前端删除一个数据。

函数原型

void push_front (const value_type& val);

void pop_front();

li.push_front(10);
li.pop_front();

5.4 链表后插入push_back() &&删除 pop_back()

push_back()表示在链表尾插入一个数据,pop_back()表示将链表尾删除一个数据。

函数原型:

void push_back (const value_type& val);

void pop_back();

li.push_back(10);li.pop_back();

5.5 插入insert()

插入元素到指定位置,通过在元素之前在指定位置插入新元素来扩展向量,从而有效地增加容器大小所插入的元素数量。

函数原型:

插入单一数据到指定位置:

iterator insert (iterator position, const value_type& val);

插入一段数据到指定位置:

void insert (iterator position, size_type n, const value_type& val);

插入一段别的容器的数据到指定位置:

template <class InputIterator>

void insert (iterator position, InputIterator first, InputIterator last);

使用举例:

	li.insert(li.begin(),10);     //在链表最前端插入数据10li.insert(li.begin(),5,20);   //在链表最前端插入5个数据内容为20list<int> k(2,50);   //创建一个新的链表k,其拥有2个元素内容均为50li.insert(li.begin(),li.begin(),li.end());  //在链表v最前端插入链表上K的全部内容

5.6 删除erase()

删除一个元素,或者是一段区间的元素,将会自动缩减空间使用。

函数原型:

iterator erase (iterator position);

iterator erase (iterator first, iterator last);

使用举例

li.erase(li.begin());     //删除第一个元素
li.erase(li.begin(),li.begin()+4); //删除前4个元素

5.7 排序sort()

让整个链表变成升序状态,或者变成自定义的排序状态

函数原型:

void sort();

template <class Compare>   void sort (Compare comp);

详细举例:

#include<iostream>
#include<list>
using namespace std;int cmp(const int &a,const int &b){ //简单的自定义降序序列return a>b;
}
int main(){list<int> li;           //创建一个空链表for(int i=10;i>=6;i--){li.push_back(i);}li.push_front(3);li.push_back(20);list<int> li2(li);for(list<int>::iterator it=li.begin();it!=li.end();it++){cout<<*it<<' ';}cout<<endl;//排序前3 10 9 8 7 6 20//li.sort();for(list<int>::iterator it=li.begin();it!=li.end();it++){cout<<*it<<' ';}cout<<endl;
//默认排序后 3 6 7 8 9 10 20//li2.sort(cmp);for(list<int>::iterator it=li2.begin();it!=li2.end();it++){cout<<*it<<' ';}cout<<endl;
//自定义排序后 20 10 9 8 7 6 3//return 0;
}

5.8 逆序reverse()

相对于自定义的降序方法,STL提供了一个默认的降序方法reverse(),类似于sort一样直接使用即可。

void reverse();

li.reverse();

 

6. List常见用法

创建list容器的函数原型:

函数原型功能
list lst;list采用采用模板类实现,对象的默认构造形式。
list(beg,end);构造函数将[beg, end)区间中的元素拷贝给本身。
list(n,elem);构造函数将n个elem拷贝给本身。
list(const list &lst);拷贝构造函数。

示例:

#include<iostream>
using namespace std;
#include<list>//list容器构造函数void printList(const list<int>&L)
{for (list<int>::const_iterator it = L.begin(); it != L.end(); it++){cout << *it << " ";}cout << endl;
}void test01()
{//创建list容器list<int>L1;  //默认构造//添加数据L1.push_back(10);L1.push_back(20);L1.push_back(30);L1.push_back(40);//遍历容器printList(L1);//区间构造方式list<int>L2(L1.begin(), L1.end());printList(L2);//拷贝构造list<int>L3(L2);printList(L3);//n个elemlist<int>L4(5, 1000);printList(L4);
}int main()
{test01();system("pause");return 0;
}

6.1 list赋值和交换

给list容器进行赋值,以及交换list容器的函数原型:

函数原型功能
assign(beg, end);将[beg, end)区间中的数据拷贝赋值给本身。
assign(n, elem);将n个elem拷贝赋值给本身。
list& operator=(const list &lst);重载等号操作符。
swap(lst);将lst与本身的元素互换。
#include<iostream>
using namespace std;
#include<list>//list容器构造函数void printList(const list<int>&L)
{for (list<int>::const_iterator it = L.begin(); it != L.end(); it++){cout << *it << " ";}cout << endl;
}void test01()
{//创建list容器list<int>L1;  //默认构造//添加数据L1.push_back(10);L1.push_back(20);L1.push_back(30);L1.push_back(40);//遍历容器printList(L1);//区间构造方式list<int>L2(L1.begin(), L1.end());printList(L2);//拷贝构造list<int>L3(L2);printList(L3);//n个elemlist<int>L4(5, 1000);printList(L4);
}int main()
{test01();system("pause");return 0;
}

6.2 list大小操作

对list容器的大小进行操作的函数原型:

函数模型功能
size();返回容器中元素的个数。
empty();判断容器是否为空。
resize(num);重新指定容器的长度为num,若容器变长,则以默认值填充新位置;如果容器变短,则末尾超出容器长度的元素被删除。
resize(num, elem);重新指定容器的长度为num,若容器变长,则以elem值填充新位置;如果容器变短,则末尾超出容器长度的元素被删除。

示例:

#include<iostream>
using namespace std;
#include<list>//list大小操作void printList(const list<int>&L)
{for (list<int>::const_iterator it = L.begin(); it != L.end(); it++){cout << *it << " ";}cout << endl;
}void test01()
{list<int>L1;L1.push_back(10);L1.push_back(20);L1.push_back(30);L1.push_back(40);printList(L1);//判断容器是否为空if (L1.empty()){cout << "L1为空!" << endl;}else{cout << "L1不为空!" << endl;cout << "L1的元素个数为:" << L1.size() << endl;}//重新指定大小L1.resize(10, 10000);printList(L1);L1.resize(2);printList(L1);
}int main()
{test01();system("pause");return 0;
}

6.3 list 插入和删除

对list容器进行数据的插入和删除的函数原型:

函数原型功能
push_back(elem);在容器尾部加入一个元素。
pop_back();删除容器中最后一个元素。
push_front(elem);在容器开头插入一个元素。
pop_front();从容器开头移除第一个元素。
insert(pos,elem);在pos位置插elem元素的拷贝,返回新数据的位置。
insert(pos,n,elem);在pos位置插入n个elem数据,无返回值。
insert(pos,beg,end);在pos位置插入[beg,end)区间的数据,无返回值。
clear();移除容器的所有数据。
erase(beg,end);删除[beg,end)区间的数据,返回下一个数据的位置。
erase(pos);删除pos位置的数据,返回下一个数据的位置。
remove(elem);删除容器中所有与elem值匹配的元素。
#include<iostream>
using namespace std;
#include<list>//list插入和删除void printList(const list<int>&L)
{for (list<int>::const_iterator it = L.begin(); it != L.end(); it++){cout << *it << " ";}cout << endl;
}void test01()
{list<int>L;//尾插L.push_back(10);L.push_back(20);L.push_back(30);//头插L.push_front(100); L.push_front(200);L.push_front(300);printList(L);  //300 200 100 10 20 30//尾删L.pop_back();printList(L);  //300 200 100 10 20//头删L.pop_front();printList(L);  //200 100 10 20//insert插入L.insert(L.begin(),1000);printList(L);  //1000 200 100 10 20list<int>::iterator it = L.begin();L.insert(++it, 20000);printList(L);  //1000 20000 200 100 10 20 //删除it = L.begin();L.erase(++it);printList(L);  //1000 200 100 10 20//移除L.push_back(10000);L.push_back(10000); L.push_back(10000);printList(L);  //1000 200 100 10 20 10000 10000 10000L.remove(10000);  //删除容器中所有与10000值匹配的元素printList(L);  //1000 200 100 10 20//清空L.clear();printList(L);  //打印一行空格
}int main()
{test01();system("pause");return 0;
}

6.4 list 数据存取

对list容器中数据进行存取的函数原型:

函数原型功能
front();返回第一个元素。
back();返回最后一个元素。

示例:

#include<iostream>
using namespace std;
#include<list>//list数据存取
void test01()
{list<int>L1;L1.push_back(10);L1.push_back(20);L1.push_back(30);L1.push_back(40);//L1[0];  //错误,不可以用[]访问list容器中的元素//L1.at(0);  //错误,不可以用at访问list容器中的元素//上述两种方式均不能访问list容器中的元素的原因是list本质是链表,不是用连续线性空间访问存储数据,迭代器也是不支持随机访问的cout << "第一个元素为:" << L1.front() << endl;cout << "最后一个元素为:" << L1.back() << endl;//验证迭代器不支持随机访问list<int>::iterator it = L1.begin();it++;  //支持双向it--;//it = it + 1;  //错误,不支持随机访问
}int main()
{test01();system("pause");return 0;
}

6.5 list反转和排序

将容器中的元素反转,以及将容器中的数据进行排序的函数原型:

函数原型功能
reverse();反转链表。
sort();链表排序。
#include<iostream>
using namespace std;
#include<list>//list反转和排序void printList(const list<int>&L)
{for (list<int>::const_iterator it = L.begin(); it != L.end(); it++){cout << *it << " ";}cout << endl;
}void test01()
{list<int>L1;L1.push_back(20);L1.push_back(10);L1.push_back(50);L1.push_back(40);L1.push_back(30);cout << "反转前:" << endl;printList(L1);L1.reverse();  // 反转cout << "反转后:" << endl;printList(L1);
}bool myCompare(int v1, int v2)
{//降序:让第一个数大于第二个数return v1 > v2;
}void test02()
{list<int>L1;L1.push_back(20);L1.push_back(10);L1.push_back(50);L1.push_back(40);L1.push_back(30);cout << "排序前:" << endl;printList(L1);//sort(L1.begin(), L1.end());  //错误,所有不支持随机访问迭代器的容器,不可以用标准算法,但其内部会提供对应一些算法L1.sort();  // 排序:默认排序规则是从小到大,即升序cout << "排序后:" << endl;printList(L1);L1.sort(myCompare);  //降序printList(L1);
}int main()
{test01();test02();system("pause");return 0;
}

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 2024年高教社杯数学建模国赛C题超详细解题思路分析
  • Linux 一个简单的中断信号实现
  • 力扣100题——子串
  • 经验笔记:SSL证书
  • Stream插件相关的用法
  • 操作系统概述及特征
  • 回溯——7.子集II
  • 【蓝桥杯嵌入式(一)程序框架和调度器】
  • 《机器学习》 基于SVD的矩阵分解 推导、案例实现
  • AI基础 L1 Introduction to Artificial Intelligence
  • k8s技术架构
  • 多维时序 | Matlab基于SSA-SVR麻雀算法优化支持向量机的数据多变量时间序列预测
  • 【论文阅读】语义通信安全研究综述(2024)
  • Simulink:循环计数器 Counter Free-Running
  • echarts进度
  • 自己简单写的 事件订阅机制
  • 【Amaple教程】5. 插件
  • 07.Android之多媒体问题
  • Git的一些常用操作
  • Iterator 和 for...of 循环
  • Linux学习笔记6-使用fdisk进行磁盘管理
  • Lucene解析 - 基本概念
  • Otto开发初探——微服务依赖管理新利器
  • Redis学习笔记 - pipline(流水线、管道)
  • Storybook 5.0正式发布:有史以来变化最大的版本\n
  • Vue学习第二天
  • Webpack 4x 之路 ( 四 )
  • 阿里云购买磁盘后挂载
  • 更好理解的面向对象的Javascript 1 —— 动态类型和多态
  • 赢得Docker挑战最佳实践
  • 用 Swift 编写面向协议的视图
  • 用jQuery怎么做到前后端分离
  • 中国人寿如何基于容器搭建金融PaaS云平台
  • 哈罗单车融资几十亿元,蚂蚁金服与春华资本加持 ...
  • 新年再起“裁员潮”,“钢铁侠”马斯克要一举裁掉SpaceX 600余名员工 ...
  • ​iOS实时查看App运行日志
  • #绘制圆心_R语言——绘制一个诚意满满的圆 祝你2021圆圆满满
  • (20)目标检测算法之YOLOv5计算预选框、详解anchor计算
  • (二)Linux——Linux常用指令
  • (附源码)spring boot火车票售卖系统 毕业设计 211004
  • (附源码)springboot掌上博客系统 毕业设计063131
  • (附源码)计算机毕业设计SSM教师教学质量评价系统
  • (七)理解angular中的module和injector,即依赖注入
  • (限时免费)震惊!流落人间的haproxy宝典被找到了!一切玄妙尽在此处!
  • (一)springboot2.7.6集成activit5.23.0之集成引擎
  • (转)C#开发微信门户及应用(1)--开始使用微信接口
  • (转)Oracle 9i 数据库设计指引全集(1)
  • .bat批处理(八):各种形式的变量%0、%i、%%i、var、%var%、!var!的含义和区别
  • .NET 8 编写 LiteDB vs SQLite 数据库 CRUD 接口性能测试(准备篇)
  • .NET CF命令行调试器MDbg入门(一)
  • .Net CoreRabbitMQ消息存储可靠机制
  • .NET Core实战项目之CMS 第一章 入门篇-开篇及总体规划
  • .NET 通过系统影子账户实现权限维持
  • .NET框架类在ASP.NET中的使用(2) ——QA
  • /bin/bash^M: bad interpreter: No such file ordirectory