3.7 list容器

3.7.1 list基本概念

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

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

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

结点的组成:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域

STL中的链表是一个双向循环链表

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-r6RhsXGp-1615016990400)(assets/clip_image002-1547608564071.jpg)]

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

list的优点:

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

list的缺点:

  • 链表灵活,但是空间(指针域) 和 时间(遍历)额外耗费较大

List有一个重要的性质,插入操作和删除操作都不会造成原有list迭代器的失效,这在vector是不成立的。

总结:STL中List和vector是两个最常被使用的容器,各有优缺点

3.7.2 list构造函数

功能描述:

  • 创建list容器

函数原型:

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

示例:

#include <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); list<int>L2(L1.begin(),L1.end());
printList(L2); list<int>L3(L2);
printList(L3); list<int>L4(10, 1000);
printList(L4);
} int main() { test01(); system("pause"); return 0;
}

总结:list构造方式同其他几个STL常用容器,熟练掌握即可

3.7.3 list 赋值和交换

功能描述:

  • 给list容器进行赋值,以及交换list容器

函数原型:

  • assign(beg, end); //将[beg, end)区间中的数据拷贝赋值给本身。
  • assign(n, elem); //将n个elem拷贝赋值给本身。
  • list& operator=(const list &lst); //重载等号操作符
  • swap(lst); //将lst与本身的元素互换。

示例:

#include <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); //赋值
list<int>L2;
L2 = L1;
printList(L2); list<int>L3;
L3.assign(L2.begin(), L2.end());
printList(L3); list<int>L4;
L4.assign(10, 100);
printList(L4); } //交换
void test02()
{ list<int>L1;
L1.push_back(10);
L1.push_back(20);
L1.push_back(30);
L1.push_back(40); list<int>L2;
L2.assign(10, 100); cout << "交换前: " << endl;
printList(L1);
printList(L2); cout << endl; L1.swap(L2); cout << "交换后: " << endl;
printList(L1);
printList(L2); } int main() { //test01(); test02(); system("pause"); return 0;
}

总结:list赋值和交换操作能够灵活运用即可

3.7.4 list 大小操作

功能描述:

  • 对list容器的大小进行操作

函数原型:

  • size(); //返回容器中元素的个数

  • empty(); //判断容器是否为空

  • resize(num); //重新指定容器的长度为num,若容器变长,则以默认值填充新位置。

    ​ //如果容器变短,则末尾超出容器长度的元素被删除。

  • resize(num, elem); //重新指定容器的长度为num,若容器变长,则以elem值填充新位置。

      	 	 						    //如果容器变短,则末尾超出容器长度的元素被删除。

示例:

#include <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); if (L1.empty())
{
cout << "L1为空" << endl;
}
else
{
cout << "L1不为空" << endl;
cout << "L1的大小为: " << L1.size() << endl;
} //重新指定大小
L1.resize(10);
printList(L1); L1.resize(2);
printList(L1);
} int main() { test01(); system("pause"); return 0;
}

总结:

  • 判断是否为空 — empty
  • 返回元素个数 — size
  • 重新指定个数 — resize

3.7.5 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 <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); //尾删
L.pop_back();
printList(L); //头删
L.pop_front();
printList(L); //插入
list<int>::iterator it = L.begin();
L.insert(++it, 1000);
printList(L); //删除
it = L.begin();
L.erase(++it);
printList(L); //移除
L.push_back(10000);
L.push_back(10000);
L.push_back(10000);
printList(L);
L.remove(10000);
printList(L); //清空
L.clear();
printList(L);
} int main() { test01(); system("pause"); return 0;
}

总结:

  • 尾插 — push_back
  • 尾删 — pop_back
  • 头插 — push_front
  • 头删 — pop_front
  • 插入 — insert
  • 删除 — erase
  • 移除 — remove
  • 清空 — clear

3.7.6 list 数据存取

功能描述:

  • 对list容器中数据进行存取

函数原型:

  • front(); //返回第一个元素。
  • back(); //返回最后一个元素。

示例:

#include <list>

//数据存取
void test01()
{
list<int>L1;
L1.push_back(10);
L1.push_back(20);
L1.push_back(30);
L1.push_back(40); //cout << L1.at(0) << endl;//错误 不支持at访问数据
//cout << L1[0] << endl; //错误 不支持[]方式访问数据
cout << "第一个元素为: " << L1.front() << endl;
cout << "最后一个元素为: " << L1.back() << endl; //list容器的迭代器是双向迭代器,不支持随机访问
list<int>::iterator it = L1.begin();
//it = it + 1;//错误,不可以跳跃访问,即使是+1
} int main() { test01(); system("pause"); return 0;
}

总结:

  • list容器中不可以通过[]或者at方式访问数据
  • 返回第一个元素 — front
  • 返回最后一个元素 — back

3.7.7 list 反转和排序

功能描述:

  • 将容器中的元素反转,以及将容器中的数据进行排序

函数原型:

  • reverse(); //反转链表
  • sort(); //链表排序

示例:

void printList(const list<int>& L) {

	for (list<int>::const_iterator it = L.begin(); it != L.end(); it++) {
cout << *it << " ";
}
cout << endl;
} bool myCompare(int val1 , int val2)
{
return val1 > val2;
} //反转和排序
void test01()
{
list<int> L;
L.push_back(90);
L.push_back(30);
L.push_back(20);
L.push_back(70);
printList(L); //反转容器的元素
L.reverse();
printList(L); //排序
L.sort(); //默认的排序规则 从小到大
printList(L); L.sort(myCompare); //指定规则,从大到小
printList(L);
} int main() { test01(); system("pause"); return 0;
}

总结:

  • 反转 — reverse
  • 排序 — sort (成员函数)

3.7.8 排序案例

案例描述:将Person自定义数据类型进行排序,Person中属性有姓名、年龄、身高

排序规则:按照年龄进行升序,如果年龄相同按照身高进行降序

示例:

#include <list>
#include <string>
class Person {
public:
Person(string name, int age , int height) {
m_Name = name;
m_Age = age;
m_Height = height;
} public:
string m_Name; //姓名
int m_Age; //年龄
int m_Height; //身高
}; bool ComparePerson(Person& p1, Person& p2) { if (p1.m_Age == p2.m_Age) {
return p1.m_Height > p2.m_Height;
}
else
{
return p1.m_Age < p2.m_Age;
} } void test01() { list<Person> L; Person p1("刘备", 35 , 175);
Person p2("曹操", 45 , 180);
Person p3("孙权", 40 , 170);
Person p4("赵云", 25 , 190);
Person p5("张飞", 35 , 160);
Person p6("关羽", 35 , 200); L.push_back(p1);
L.push_back(p2);
L.push_back(p3);
L.push_back(p4);
L.push_back(p5);
L.push_back(p6); for (list<Person>::iterator it = L.begin(); it != L.end(); it++) {
cout << "姓名: " << it->m_Name << " 年龄: " << it->m_Age
<< " 身高: " << it->m_Height << endl;
} cout << "---------------------------------" << endl;
L.sort(ComparePerson); //排序 for (list<Person>::iterator it = L.begin(); it != L.end(); it++) {
cout << "姓名: " << it->m_Name << " 年龄: " << it->m_Age
<< " 身高: " << it->m_Height << endl;
}
} int main() { test01(); system("pause"); return 0;
}

总结:

  • 对于自定义数据类型,必须要指定排序规则,否则编译器不知道如何进行排序

  • 高级排序只是在排序规则上再进行一次逻辑规则制定,并不复杂

更多信息请关注公众号:

[C++提高编程] 3.7 list容器的更多相关文章

  1. 15个提高编程技巧的JavaScript工具

    原文地址:http://www.imooc.com/wenda/detail/243523 JavaScript脚本库是一个预先用JavaScript语言写好的库,它方便了我们开发基于JavaScri ...

  2. 17款提高编程效率的css工具

    参看下面链接:<17款提高编程效率的css工具>

  3. C++编程 - tuple、any容器

    C++编程 - tuple.any容器 flyfish 2014-10-29 一 tuple tuple是固定大小的容器,每一个元素类型能够不同 作用1 替换struct struct t1 { in ...

  4. 提高编程能力的7条建议 分类: T_TALENT 2014-04-12 10:41 294人阅读 评论(0) 收藏

    编程是非常酷的一件事情,但是在酷炫的背后它对很多人来说还是挺难的.很多人在学习编程之初就被困难击败了. 当你不熟悉编程的时候,你可能会觉得无从下手,并且不知道如何运用学到的知识.只要你通过了这一困难的 ...

  5. 【Java并发编程二】同步容器和并发容器

    一.同步容器 在Java中,同步容器包括两个部分,一个是vector和HashTable,查看vector.HashTable的实现代码,可以看到这些容器实现线程安全的方式就是将它们的状态封装起来,并 ...

  6. Java编程思想之十七 容器深入研究

    17.1 完整的容器分类方法 17.2 填充容器 import java.util.*; class StringAddress { private String s; public StringAd ...

  7. PHP提高编程效率的方法,你知道多少呢?

    PHP语言是最WEB的计算机语言,而且也是应用最广泛的语言,那么PHP对编程的影响有多大呢?下面可以去了解一下. 用单引号代替双引号来包含字符串,这样做会更快一些.因为PHP会在双引号包围的字符串中搜 ...

  8. 深入理解java:2.3.5. 并发编程concurrent包 之容器BlockingQueue(阻塞队列)

    1. 什么是阻塞队列? 阻塞队列(BlockingQueue)是一个支持两个附加操作的队列. 这两个附加的操作是:在队列为空时,获取元素的线程会等待队列变为非空. 当队列满时,存储元素的线程会等待队列 ...

  9. 深入理解java:2.3.3. 并发编程concurrent包 之容器ConcurrentHashMap

    线程不安全的HashMap 因为多线程环境下,使用Hashmap进行put操作会引起死循环,导致CPU利用率接近100%,所以在并发情况下不能使用HashMap. 效率低下的HashTable容器 H ...

  10. 第34天学习打卡(GUI编程之组件和容器 frame panel 布局管理 事件监听 多个按钮共享一个事件 )

    GUI编程 组件 窗口 弹窗 面板 文本框 列表框 按钮 图片 监听事件 鼠标 键盘事件 破解工具 1 简介 GUi的核心技术:Swing AWT 1.界面不美观 2.需要jre环境 为什么要学习GU ...

随机推荐

  1. (6) JavaScript - Math对象与日期对象

    1 认识对象 概念:对象就是一种类型,一种引用类型,而对象则是引用类型的实例.在ECMAScript中,引用类型是一种数据结构,用于将数据和功能组织在一起,通常它也被称作类. 面向过程思想:只考虑过程 ...

  2. C Ⅷ

    数组  int number[100];   //这个数组可以放100个数 int x; int cnt = 0; double sum = 0; scanf("%d", & ...

  3. []Python][simple]Serialize data with Pickle and deserialize data from pickle

    序列化 import pickle friend = {"Dan": [20, "Lodon", 123123], "Mary" : [24 ...

  4. Axure RP Extension for Chrome 0.6.2安装和详解

    1.当我们用网页访问一个本地页面时就会出现这种问题,提示你要安装浏览器的扩展程序包,以下有搜狗浏览器如何安装,qq浏览器 ​

  5. 6. 基础查(会员信息) - 创建查询Web Api - 配置Table Permission

    ​ Power Portal中的Web API可以对门户页面中所有的Microsoft Dataverse实体进行创建.更新和删除操作.我们可以直接使用门户Web API对产品创建新客户.更新联系人或 ...

  6. pytorch之科学计算

    一.简介 torch作为深度学习的主流框架,其根本在于1.具有强大的GPU加速的张量计算功能.2.包含自动求导系统的深度神经网络.自动求导功能由torch.Autograd模块实现,而科学计算部分则直 ...

  7. NodeJs 版本管理

    nvm-windows 说明:nvm是Nodejs的版本管理器.在开发中项目可能需要低版本或者高版本的Nodejs运行环境,以此我们可以使用nvm来切换Nodejs的版本. 在安装NVM for Wi ...

  8. 针对于Sql server突然连接不到服务器的解决方法

    问题叙述 点击连接之后,总是会弹出一个错误弹窗: 方法解决 快捷键Win+R,输入services.msc,进入到服务界面: 找到SQL 代理(DEV) 将手动打开改成自动 再连接试一次 连上啦! ( ...

  9. 小白都能看懂得Xxl-job安装教程

    大家好,我是咔咔 不期速成,日拱一卒 一.背景 在平时的业务场景中,经常有一些场景需要使用定时任务,比如: 某个时间点发送优惠券 发送短信等等. 批量处理数据:批量统计上个月的账单,统计上个月销售数据 ...

  10. Gym 101490K Safe Racing (dp转换, 超超超级详细,包你看懂)

    题意:给你一个长为L的圆形跑道,让你放置警示牌,相邻两个警示牌相隔距离不能超过S,让你求有多少种方案数放置.数据L,S都是1e6. 来个例子:L = 13, S = 5.一个圈表示长度为1. 思路:因 ...