31,list容器

news2024/11/25 6:36:53

31.1list基本概念

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

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

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

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

链表的优点:

可以快速对任意位置进行快速插入或删除元素

链表的缺点:

容器遍历速度没有数组快

占用空间比数组大

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

(双向:每个结点记录了上一个位置也记录了下一个位置)

(循环:最后一个结点也记录的是第一个结点位置,第一个结点也记录了最后一个结点位置)

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

list的优点 :

采用动态存储分配,不会造成内存浪费和溢出

链表执行插入和删除操作十分方便,修改指针即可,不需要移动大量元素

list的缺点:

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

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

(箭头为迭代器,vector容器数组中内存不够了,把所以数据转移到新的内存,原来的迭代器(箭头)就失效了。链表中随便插入删除都不会影响)

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

31.2list构造函数

功能描述:创建list容器

函数原型:

list<T>lst;                 //list采用模板类实现,对象的默认构造形式

list(beg,end);           //构造函数将[beg,end)区间中的元素拷贝给本身

list(n,elem);             //构造函数将n个elem拷贝给本身

list(const list &lst);   //拷贝构造函数

#include<iostream>
using namespace std;
#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;
	for (int i = 0; i < 10; i++)
	{
		l1.push_back(i);
		l1.push_front(i);
	}
	printList(l1);
	//输出结果:9 8 7 6 5 4 3 2 1 0 0 1 2 3 4 5 6 7 8 9

	list<int>l2(l1.begin(), l1.end());
	printList(l2);
	//输出结果:9 8 7 6 5 4 3 2 1 0 0 1 2 3 4 5 6 7 8 9

	list<int>l3(5, 10);
	printList(l3);
	//输出结果:10 10 10 10 10

	list<int>l4(l1);
	printList(l4);
	//输出结果:9 8 7 6 5 4 3 2 1 0 0 1 2 3 4 5 6 7 8 9
}
int main()
{
	test01();
	system("pause");
	return 0;
}

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

31.3list赋值

功能描述:给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>
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;
	for (int i = 0; i < 10; i++)
	{
		l1.push_back(i);
		l1.push_front(i);
	}
	printList(l1);
	//输出结果:9 8 7 6 5 4 3 2 1 0 0 1 2 3 4 5 6 7 8 9

	list<int>l2;
	l2.assign(l1.begin(), l1.end());
	printList(l2);
	//输出结果:9 8 7 6 5 4 3 2 1 0 0 1 2 3 4 5 6 7 8 9

	list<int>l3;
	l3.assign(5, 10);
	printList(l3);
	//输出结果:10 10 10 10 10

	list<int>l4;
	l4 = l1;
	printList(l4);
	//输出结果:9 8 7 6 5 4 3 2 1 0 0 1 2 3 4 5 6 7 8 9

	l4.swap(l3);
	printList(l3);
	//输出结果:9 8 7 6 5 4 3 2 1 0 0 1 2 3 4 5 6 7 8 9
	printList(l4);
	//输出结果:10 10 10 10 10
}
int main()
{
	test01();
	system("pause");
	return 0;
}

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

31.4list大小操作

功能描述;对list容器的大小进行操作

函数原型:

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

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

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

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

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

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

#include<iostream>
using namespace std;
#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;
	for (int i = 0; i < 10; i++)
	{
		l1.push_back(i);
		l1.push_front(i);
	}
	printList(l1);
	//输出结果:9 8 7 6 5 4 3 2 1 0 0 1 2 3 4 5 6 7 8 9

	if(!l1.empty())
	{
		cout << "l1不为空" << endl;
		cout << "l1大小:" << l1.size() << endl;
	}
	else 
	{
		cout << "l1位空" << endl;
	}
	//输出结果:l1不为空
	//          l1大小:20

	l1.resize(25);
	printList(l1);
	//输出结果:9 8 7 6 5 4 3 2 1 0 0 1 2 3 4 5 6 7 8 9 0 0 0 0 0

	l1.resize(10);
	printList(l1);
	//输出结果:9 8 7 6 5 4 3 2 1 0

	l1.resize(15, 10);
	printList(l1);
	//输出结果:9 8 7 6 5 4 3 2 1 0 10 10 10 10 10
}
int main()
{
	test01();
	system("pause");
	return 0;
}

总结:

判断是否位空--empty

返回元素个数--size

重新指定个数--resize

31.5list插入和删除

功能描述:对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值匹配的元素 (如移除所有0)

#include<iostream>
using namespace std;
#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;
	for (int i = 0; i < 10; i++)
	{
		l1.push_back(i);
	}
	printList(l1);
	//输出结果:0 1 2 3 4 5 6 7 8 9

	l1.pop_back();
	printList(l1);
	//输出结果:0 1 2 3 4 5 6 7 8

	l1.pop_front();
	printList(l1);
	//输出结果:1 2 3 4 5 6 7 8

	list<int>l2;
	l2.push_front(5);
	l2.push_front(4);
	l2.push_front(3);
	l2.push_front(2);
	l2.push_front(1);
	printList(l2);
	//输出结果:1 2 3 4 5

	l1.insert(l1.begin(), 0);
	printList(l1);
	//输出结果:0 1 2 3 4 5 6 7 8

	l1.insert(l1.end(), 5, 0);
	printList(l1);
	//输出结果:0 1 2 3 4 5 6 7 8 0 0 0 0 0

	l1.insert(l1.begin(), l2.begin(), l2.end());
	printList(l1);
	//输出结果:1 2 3 4 5 0 1 2 3 4 5 6 7 8 0 0 0 0 0

	l2.clear();
	if (!l2.empty())
	{
		cout << "l2不为空" << endl;
	}
	else
	{
		cout << "l2为空" << endl;
	}
	//输出结果:l2为空

	l1.remove(0);
	printList(l1);
	//输出结果:1 2 3 4 5 1 2 3 4 5 6 7 8

	l1.erase(l1.begin());
	printList(l1);
	//输出结果:2 3 4 5 1 2 3 4 5 6 7 8

	l1.erase(l1.begin(), l1.end());
	if (!l1.empty())
	{
		cout << "l1不为空" << endl;
	}
	else
	{
		cout << "l1为空" << endl;
	}
	//输出结果:l1为空
}
int main()
{
	test01();
	system("pause");
	return 0;
}

 insert插入,erase删除start后一位

#include<iostream>
using namespace std;
#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;
	for (int i = 0; i < 10; i++)
	{
		l1.push_back(i);
	}
	printList(l1);
	//输出结果:0 1 2 3 4 5 6 7 8 9

	list<int>::iterator it = l1.begin();
	l1.insert(++it, 1000);
	printList(l1);
	//输出结果:0 1000 1 2 3 4 5 6 7 8 9
    
    it=l1.begin();
    l1.erase(++it);
    printList(l1);
    //输出结果:0 1 2 3 4 5 6 7 8 9
}
int main()
{
	test01();
	system("pause");
	return 0;
}

总结:

尾插--push_back

尾删--pop_back

头插--push_front

头删--pop_front

插入--insert

删除--erase

移除--remove

清空--clear

31.6list数据存取

功能描述:对list容器中数据进行存取

函数原理:

front();      //返回第一个元素

back();      //返回最后一个元素

#include<iostream>
using namespace std;
#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;
	for (int i = 0; i < 10; i++)
	{
		l1.push_back(i);
	}
	printList(l1);
	//输出结果:0 1 2 3 4 5 6 7 8 9

	cout << "l1第一个元素:" << l1.front() << endl;
	//输出结果:l1第一个元素:0
	l1.front() = 10;
	cout << "l1第一个元素:" << l1.front() << endl;
	//输出结果:l1第一个元素:10
	printList(l1);
	//输出结果:10 1 2 3 4 5 6 7 8 9

	cout << "l1最后一个元素:" << l1.back() << endl;
	//输出结果:l1最后一个元素:9
	l1.back() = 10;
	cout << "l1最后一个元素:" << l1.back() << endl;
	//输出结果:l1最后一个元素:10
	printList(l1);
	//输出结果:10 1 2 3 4 5 6 7 8 10

	//l1[0]不可以用[]访问list容器中的元素
	//l1.at(0)不可以用at方式访问list容器中的元素
	//原因是list本质为链表,不是用连续线性空间存储数据,迭代器也不支持随机访问
}
int main()
{
	test01();
	system("pause");
	return 0;
}

验证迭代器是不支持随机访问的

#include<iostream>
using namespace std;
#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;
	for (int i = 0; i < 10; i++)
	{
		l1.push_back(i);
	}
	printList(l1);
	//输出结果:0 1 2 3 4 5 6 7 8 9

	//验证迭代器是不支持随机访问的
	list<int>::iterator it = l1.begin();
	it++;//可以it++,不可以 it = it + 1;,证明不支持随机访问
	it--;//支持双向
}
int main()
{
	test01();
	system("pause");
	return 0;
}

总结:

list容器中不可以通过[]或者at方式访问数据

返回第一个元素--front

返回最后一个元素--back

31.7list反转和排序

功能描述:将容器中的元素反转,以及将容器中的数据进行排列

函数原型;

reverse();    //反转链表

sort();           //链表排序

#include<iostream>
using namespace std;
#include<list>
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 v1, int v2)
{
	//降序  就让第一个数>第二个数
	return v1 > v2;
}
void test01()
{
	list<int>l1;
	l1.push_back(5);
	l1.push_back(2);
	l1.push_back(1);
	l1.push_back(7);
	l1.push_back(4);
	l1.push_back(9);
	l1.push_back(3);
	l1.push_back(8);
	l1.push_back(6);
	printList(l1);
	//输出结果:5 2 1 7 4 9 3 8 6

	l1.reverse();
	printList(l1);
	//输出结果:6 8 3 9 4 7 1 2 5

	l1.sort();
	printList(l1);
	//输出结果:1 2 3 4 5 6 7 8 9

	//所有不支持随机访问迭代器的容器,不可以用标准算法
	//不支持随机访问迭代器的容器,内部会提供对应一些算法
	//不可以用全局函数如sort(l1.begin(),l1.end());

	//降序
	l1.sort(myCompare);
	printList(l1);
	//输出结果:9 8 7 6 5 4 3 2 1
}
int main()
{
	test01();
	system("pause");
	return 0;
}

总结:

反转--reverse

排序--sort(成员函数)

31.8排序案例

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

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

#include<iostream>
using namespace std;
#include<list>
class Person
{
public:
	Person(string name, int age, int hight)
	{
		this->m_Name = name;
		this->m_Age = age;
		this->m_Hight = hight;
	}
public:
	string m_Name;
	int m_Age;
	int m_Hight;
};
bool comparePerson(Person& p1, Person& p2)
{
	if (p1.m_Age == p2.m_Age)//年龄相同时按身高降序
	{
		return p1.m_Hight > p2.m_Hight;
	}
	return p1.m_Age < p2.m_Age;//按照年龄升序
}
void test01()
{
	list<Person>l;
	Person p1("张三", 10, 180);
	Person p2("李四", 30, 160);
	Person p3("王五", 20, 190);
	Person p4("赵六", 30, 170);
	l.push_back(p1);
	l.push_back(p2);
	l.push_back(p3);
	l.push_back(p4);
	for (list<Person>::iterator it = l.begin(); it != l.end(); it++)
	{
		cout << "姓名:" << it->m_Name << " 年龄:" << it->m_Age << " 身高:" << it->m_Hight << endl;
	}
	cout << "--------------------------------" << 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_Hight << endl;
	}
}
int main()
{
	test01();
	system("pause");
	return 0;
}

输出结果: 

姓名:张三 年龄:10 身高:180
姓名:李四 年龄:30 身高:160
姓名:王五 年龄:20 身高:190
姓名:赵六 年龄:30 身高:170
--------------------------------
排序后:
姓名:张三 年龄:10 身高:180
姓名:王五 年龄:20 身高:190
姓名:赵六 年龄:30 身高:170
姓名:李四 年龄:30 身高:160

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/771819.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【剧前爆米花--web】HTTP协议格式详解以及构造

作者&#xff1a;困了电视剧 专栏&#xff1a;《JavaEE初阶》 文章分布&#xff1a;这是一篇关于HTTP协议的文章&#xff0c;在这篇文章中我会说明HTTP协议格式以及相关的构造&#xff0c;希望对你有所帮助&#xff01; 目录 HTTP协议 HTTP协议格式 HTTP请求 HTTP响应详情…

拿了 7 个大厂 offer,我有话说

我有一个朋友&#xff0c;举办了一个分享会。他春招期间收割了阿里、京东、美团、拼多多、网易、腾讯云智等多家公司的实习 offer。 他最近从一家A大厂实习换到了另外一家B大厂实习&#xff0c;分享会长达100分钟&#xff0c; 共解答了 40 多个问题。 我也从中抽取一些比较有共…

一个小技巧,分分钟搞定新零售!

新零售模式的兴起带来了线上线下销售渠道的整合&#xff0c;而自动售货机作为新零售模式的一种重要形式&#xff0c;提供了便捷的自助购物体验。 自动售货机作为新零售模式的一种典型应用&#xff0c;以其便利性、快捷性和24小时无人值守的特点&#xff0c;深受消费者和商家的青…

MySQL数据库 【增删改查】

目录 一、新增 指定列插入 一次插入多个数据 二、查询 1、全列查询 2、指定列查询 3、查询字段为表达式 4、查询的时候给列名/表达式 指定别名 5、查询时去重 6、排序查询 7、条件查询 8、模糊查询 9、空值查询 10、分页查询 三、修改 四、删除 SQL 最核心…

python如何知道你的导包在哪/site-package在哪/anaconda中的模块文件在哪

参考: https://stackoverflow.com/questions/31003994/where-is-site-packages-located-in-a-conda-environment anaconda虚拟环境中的site-package在如下目录&#xff0c;/opt/conda/envs/env_cp37_STAGATE_TF/lib/python3.7/site-packages/。 基于寻找你导包的物理位置在哪…

婚纱照主题定义

文章目录 前言关于我们听我们说关于风格&#xff1a;1、主纱&#xff08;内&#xff09;2、工笔画&#xff08;内&#xff09;3、个性潮拍 &#xff08;内&#xff09;4、森系&#xff08;外&#xff09;5、园林&#xff08;外&#xff09;写在最后 前言 非常感谢在今生有约婚…

doris恢复库恢复表

今天眼疾手快 不小心删了公司生产环境的表 而且碰巧这个数据没有备份的 当时哥们就呆住 还好doris升级过1.2 刚推出了恢复数据的功能~~~~~这里给老天爷磕一个了~~~~~~ 数据删除恢复 Doris为了避免误操作造成的灾难&#xff0c;支持对误删除的数据库/表/分区进行数据恢复&…

什么是DIN连接器 DIN连接器的应用

一、什么是DIN连接器 DIN连接器是一种遵循德国国家标准化组织制定的连接器标准的电子连接器。它采用圆形外观和标准化的接口设计&#xff0c;以确保与其他符合DIN标准的设备和连接器的兼容性。DIN连接器通常由插头和插座两部分组成&#xff0c;通过插拔操作实现电路的连接和断开…

面试时被问到职业规划,怎样回答才最加分?

很多人被问到「职业规划」这个问题的时候&#xff0c;都会很………纠结&#xff1a; 表现得太踏实苦干了&#xff0c;可能会让人觉得没有什么进取心。 职业目标描述得太明确&#xff0c;又会被质疑太在意外部激励而缺乏内部动机。 感觉怎么说都会错&#xff0c;说多一句都是…

Java 中 synchronized 的优化操作:锁升级、锁消除、锁粗化

由 并发编程中常见的锁策略 总结可知&#xff0c;synchronized 具有以下几个特性&#xff1a; 开始时是乐观锁&#xff0c;如果锁冲突频繁&#xff0c;就转换为悲观锁。开始是轻量级锁实现&#xff0c;如果锁被持有的时间较长&#xff0c;就转换成重量级锁。实现轻量级锁时&am…

预处理详解(二)---#define 定义宏 + 宏的使用 + 宏和函数的区别

文章目录 #define 定义标识符#define 定义宏#define 的替换规则带副作用的宏参数宏和函数的区别#undef 的作用冷门知识点&#xff1a;#与## #define 定义标识符 #define定义标识符的格式如下&#xff1a; #define MAX 100 #define reg register//懒人觉得register太长了这些被…

Virus Total 曝数据泄露大事件:涉及多国情报部门

The Hacker News 网站披露&#xff0c;可疑文件和病毒在线检测平台 VirusTotal 曝出数据泄露事故&#xff0c;一名员工无意中将部分 VirusTotal 注册客户的姓名、电子邮件地址等敏感数据信息上传到了恶意软件扫描平台&#xff0c;此举导致约 5600 名用户数据泄露。 据悉&#x…

Display

Pipeline Dataloader和后面网络训练是解耦的&#xff0c;Dataloader负责把数据读出来变成tensor&#xff0c;网络&#xff08;继承nn.Module父类&#xff09;负责把这tensor算成最后的输出。在网络传播的过程中&#xff0c;hook记录保留中间数据&#xff0c;用于display作图。…

CSS——基础知识及使用

CSS 是什么 CSS是层叠样式表 (Cascading Style Sheets)的简写.CSS 能够对网页中元素位置的排版进行像素级精确控制, 实现美化页面的效果. 能够做到页面的样式和结构分离。 基本语法规范 选择器 { 一条/N条声明 } 选择器决定针对谁修改 (找谁)声明决定修改啥. (干啥)声明的…

PP速度模式应用

应用场景要求&#xff1a; 电机在变化的负载下&#xff0c;保持设定的速度时&#xff0c;需要使用速度模式。 在速度模式下&#xff0c;电机速度由发送到电机的电压控制。但是要改变电机的速度&#xff08;加速或减速&#xff09;需要增加或减小电机转矩&#xff0c;因此在速度…

Stable Diffusion - 编辑生成 (OpenPose Editor) 相同人物姿势的图像

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/131818943 OpenPose Editor 是 Stable Diffusion 的扩展插件&#xff0c;可以自定义人物的姿势和表情&#xff0c;以及生成深度、法线和边缘图等信…

rt-thread rtc设备驱动开发

基于pico rtc设备驱动开发 I/O设备框架RTC设备功能配置——启用Soft RTC功能配置——启用NTP时间自动同步功能配置——启用硬件RTC RT-Thread 的 RTC &#xff08;实时时钟&#xff09;设备为操作系统的时间系统提供了基础服务。应用层对于 RTC 设备一般不存在直接调用的 API &…

three.js学习

前言&#xff1a; three.js基本使用没问下&#xff0c;下面进入自定义图形 效果展示 实现 使用BufferGeometry()自定义 <script setup lang"ts"> import { ref, onMounted } from vue import * as THREE from three // 导入轨道控制器 import { OrbitContro…

Java对象深拷贝、浅拷贝之枚举类型

问题&#xff1a;为什么属于引用类型的enum不会有深拷贝浅拷贝的问题&#xff1f; 解释&#xff1a; 在Java中&#xff0c;枚举类型是一种特殊的类类型。每个枚举值都是该枚举类型的一个实例&#xff0c;并且这些实例在枚举类型被初始化时就已经被创建。这些实例在程序的整个…