C++——list

一、基本概念

list就是带头的循环双向链表模板类。它的迭代器是双向迭代器,不支持[ ]的重载和用+/-随机访问数据。

(1)

三、常用接口

构造、迭代器、empty、size、front、back、不支持[ ]重载、assign、push_front、pop_front、push_back、pop_back、insert、erase、swap、resize、clear、、、、、、

迭代器不是原生指针,由于物理上内存不是连续的,所以不能通过迭代器 + e 来访问下一个位置的元素

二、迭代器的分类

(1)按照性质进行分类

①输入/只读迭代器(Input Iterator)

输入迭代器又叫只读迭代器。类似于一个只能读数据,不能修改数据,仅支持++,不支持--的指针。通常用于单向向后遍历。

②输出/只写迭代器(Output Iterator)

输出迭代器又叫只写迭代器。类似于一个只能写数据,不能读取数据,仅支持++,不支持--的指针。通常用于从单向向后写入。

③前向迭代器/单向(读写)迭代器(Forward Iterator)

输出迭代器又叫只写迭代器。类似于一个可以读可写数据,仅支持++,不支持--的指针。通常用于从单向向后遍历写入。(和只读迭代器一样,要想修改某个位置的数据,只能通过遍历去修改)
这里以forward_list(不带头的不循环的单向链表类模板)。由于单链表在物理结构上不是连续的(遍历时不能使用+/-,不能通过下标访问某个节点的数据),而且不能往回遍历(不能使用--)。所以在设计它的迭代器时也就设计成了前向迭代器。

下面用具体的代码感受一下:

cpp 复制代码
#include<iostream>
#include<forward_list>
using namespace std;
//单向迭代器
int main() {
	forward_list<int> f{1,2,3};
	forward_list<int>::iterator it = f.begin();
	cout << *it << endl;//可读
    ++it;//仅支持++
	cout << *it << endl;//可写
	//--it;//不支持--会报错
}

④双向迭代器/双向读写迭代器(Bidirectional Iterator)

双向迭代器又叫做双向读写迭代器。类似于一个可以读可写数据,支持++/--的指针。通常用于从双向遍历和写入。(和只读迭代器一样,要想修改某个位置的数据,只能通过遍历去修改)

由于list带头双向循环链表的设计,所以它的迭代器也就设计成了双向迭代器。

⑤随机访问迭代器(Random Access Iterator)

随机访问迭代器又叫做随机读写迭代器。类似于一个可以读可写数据,既支持 ++--,还支持加减整数、下标访问、大小比较的指针。即能双向遍历,也可以通过下标随机访问数据,类似于顺序表。

string和vector的底层是数组。根据这种结构string和vector的迭代器就被设计成了随机访问迭代器。

string迭代器

vector迭代器

(2)迭代器按照功能进行分类

迭代器按照功能共有四种。分别是普通迭代器和反向迭代器以及他们的const版本------普通只读迭代器,普通反向迭代器。

三、list常用接口

(1)构造

①无参的默认构造

创建一个空的list(仅带哨兵位)。

cpp 复制代码
int main() {
	list<int> l;//调用默认构造
}

②填充构造

创建n个值为val的list。

cpp 复制代码
int main() {
	list<int> l(5,0);//填充构造
	for (auto e : l) {
		cout << e << "->";
	}
	cout << endl;
}

③迭代器范围构造

用迭代器进行构造,但是需要注意list的迭代器是双向迭代器。不支持+/-,仅支持++/--

cpp 复制代码
int main() {
	list<int> l1(10,0);//填充构造
	//list<int> l2(l1.begin(),l1.begin() + 3);//错误写法,list迭代器是双向读写迭代器
	auto last = l1.begin();
	++last;
	++last;
	++last;
	list<int> l2(l1.begin(), last);//迭代器构造
	for (auto e : l2) {
		cout << e << "->";
	}
	cout << endl;
}

④拷贝构造

用另一个list实例化对象实例化另一个对象。

cpp 复制代码
int main() {
	list<int> l1(5, 1);
	list<int> l2(l1);//拷贝构造
	for (auto e : l2) {
		cout << e << "->";
	}
	cout << endl;
}

(2)empty

判断链表是否为空链表;为空,输出1;不为空,输出0

cpp 复制代码
int main() {
	list<int> l1;
	list<int> l2(5, 0);
	cout << l1.empty() << endl;
	cout << l2.empty() << endl;
}

(3)size

计算链表中的节点个数。

cpp 复制代码
int main() {
	list<int> l(100, 0);
	cout << l.size() << endl;
}

(4)front和back

①front

返回list中的第一个元素的引用。reference是list中节点的引用。

②back

返回list中最后一个元素的引用。

cpp 复制代码
int main() {
	list<int> l{10,20,30};
	cout << l.front() << endl;
	cout << l.back() << endl;
}

(5)assign

清空原list并重新对它进行初始化工作。可以形象的理解为先调clear,再调对应的构造。

cpp 复制代码
int main() {
	list<int> l1(3, 0);
	list<int> l2{1,2,3,4,5};
	l1.assign(l2.begin(), l2.end());//使用迭代器范围接口
	Print(l1);

	l1.assign(5,0);//使用填充接口
	Print(l1);

	l1.assign({10,20,30});//使用初始化列表接口C++11引入
	Print(l1);
}

(6)push_front/pop_front

头插和头删。

cpp 复制代码
void Print(list<int> l) {
	for (auto e : l) {
		cout << e << "->";
	}
	cout << endl;
}
int main() {
	list<int> l(3, 0);
	l.push_front(100);//头插
	Print(l);
	l.pop_front();//头删
	Print(l);
}

(7)push_back/pop_back

尾插和尾删

cpp 复制代码
void Print(list<int> l) {
	for (auto e : l) {
		cout << e << "->";
	}
	cout << endl;
}
int main() {
	list<int> l(3, 0);
	l.push_back(100);//尾插
	Print(l);
	l.pop_back();//尾删
	Print(l);
}

(8)insert

①next(C++11引入)

使用时必须包含头文件iterator
功能:list的迭代器是一个双向迭代器,无法直接访问某个数据,只能一步步的++或者--。而设计next就是实现了多次的++。
函数原型解释:它有两个参数,第一个参数是当前位置的迭代器,第二个参数是要移动的步数,缺省值为1。返回值类型为当前迭代器的类型

cpp 复制代码
#include<iostream>
#include<list>
#include<iterator>
using namespace std;
int main() {
	list<int> l1{10,20,30,40,50};
	list<int> l2(l1.begin(),next(l1.begin(),3));//迭代器构造
		for (auto e : l2) {
		cout << e << "->";
	}
	cout << endl;
}

②insert

在指定位置插入之前数据。(在迭代器指向的元素之前插入数据)

cpp 复制代码
void Print(list<int> l) {
	for (auto e : l) {
		cout << e << "->";
	}
	cout << endl;
}

int main() {
	list<int> l1{10,20,30,40,50};
	l1.insert(next(l1.begin(),2),100);//在某个位置插入单个元素,迭代器指向的是30这个节点,100在30之前插入
	Print(l1);

	list<int> l2{ 10,20,30,40,50 };
	l2.insert(++l2.begin(),3,100);//在某个位置插入n个val,迭代器指向的是20这个节点,100在20之前插入
	Print(l2);

	list<int> l3{ 10,20,30,40,50 };
	list<int> l4(3,0);
	l3.insert(++l3.begin(),l4.begin(),l4.end());//迭代器插入
	Print(l3);

	list<int> l5{ 10,20,30,40,50 };
	l5.insert(l5.begin(), {666,666,666});//初始化列表插入
	Print(l5);
} 

(9)erase

删除指定位置的节点。

cpp 复制代码
void Print(list<int> l) {
	for (auto e : l) {
		cout << e << "->";
	}
	cout << endl;
}
int main() {
	list<int> l1{10,20,30,40,50};
	l1.erase(next(l1.begin(),2));//删除单个元素
	Print(l1);

	list<int> l2{ 10,20,30,40,50 };
	l2.erase(++l2.begin(),--l2.end());//删除迭代器范围内的节点
	Print(l2);
}

(10)swap

交换两个实例化后list对象的内容。

cpp 复制代码
int main() {
	list<int> l1(5, 0);
	list<int> l2(5, 1);
	cout << "l1交换前:";
	Print(l1);
	cout << "l2交换前:";
	Print(l2);
	l1.swap(l2);
	cout << "l1交换后:";
	Print(l1);
	cout << "l2交换后:";
	Print(l2);
}

(11)resize

调整有效元素的个数。

(12)clear

清理节点空间。


相关推荐
handler011 小时前
Git 核心指令速查
linux·c语言·c++·笔记·git·学习
fish_xk1 小时前
c++中的多态
c++
汉克老师1 小时前
GESP2025年6月认证C++五级( 第三部分编程题(1、奖品兑换))
c++·二分算法·gesp5级·gesp五级
hopetomorrow1 小时前
学习路之PHP --PHP 常用扩展及作用表
开发语言·学习·php
Lhan.zzZ1 小时前
笔记_2026.4.28_003
c++·笔记·qt·opencv
simple-L61 小时前
Java开发痛点技术文章大纲
java·开发语言
stolentime2 小时前
我常常追忆过去
c++·里程碑纪念
m0_635647482 小时前
Qt打包含有第三方库的软件为应用程序——CQtDeployer
开发语言·数据库·qt
fengenrong2 小时前
20260429
c++·算法