C++STL——list容器及其常用操作(详解)

在这里插入图片描述
纵有疾风起,人生不言弃。本文篇幅较长,如有错误请不吝赐教,感谢支持。

一.list容器基本概念

链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。
每个结点包括两个部分:

  • 一个是存储数据元素的数据域。
  • 另一个是存储下一个结点地址的指针域。
    在这里插入图片描述

list容器的数据结构是一个有头双向循环链表。链表其优缺点为:

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

list容器的迭代器:
list容器不能像vector一样以普通指针作为迭代器,因为其节点不能保证在同一块连续的内存空间上。list迭代器必须有能力指向list的节点,并有能力进行正确的递增、递减、取值、成员存取操作。所谓”list正确的递增,递减、取值、成员取用”是指,递增时指向下一个节点,递减时指向上一个节点,取值时取的是节点的数据值,成员取用时取的是节点的成员。由于list还是一个双向链表,迭代器必须能够具备前移、后移的能力,所以list容器提供的是双向迭代器(Bidirectional Iterators).
在这里插入图片描述

二.list容器的常用操作

list构造函数

注:使用list容器时,需包含头文件#include <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>& mylist)//形参使用const,避免被修改
{//const_iterator只读迭代器
	for (list<int>::const_iterator it = mylist.begin(); it != mylist.end(); ++it)
	{
		cout << *it << " ";
	}
	cout << endl;
}
void test()
{
	list<char> mylist1;//list采用模板实现类实现(显示实例化),对象的默认构造形式。
	list<int> mylist2(10, 6); //构造函数将n个elem拷贝给本身。
	list<int> mylist3(++mylist2.begin(), --mylist2.end());//构造函数将[beg, end)区间中的元素拷贝给本身。
	list<int> mylist4(mylist2);//拷贝构造函数

	printList(mylist2);
	printList(mylist3);
	printList(mylist4);
}
int main()
{
	test();
	return 0;
}

在这里插入图片描述

list迭代器获取

在这里插入图片描述

获取正向迭代器iterator:

函数原型解释
iterator begin();返回指向开始位置的迭代器,iterator是正向迭代器。只能使用++运算符从左向右遍历容器,每次沿容器向右移动一个元素
const_iterator begin();返回指向开始位置并且为常量的迭代器
const_iterator cbegin();返回指向开始并且为常量的迭代器,const_iterator 常正向迭代器。函数作用:配合auto使用
iterator end();返回指向末尾元素的下一个位置的迭代器
const_iterator end();返回指向末尾元素的下一个位置并且为常量的迭代器
const_iterator cend();返回指向末尾元素的下一个位置的并且为常量的迭代器,函数作用:配合auto使用

获取反向迭代器reverse_iterator:

函数原型解释
reverse_iterator rbegin();返回反向迭代器,指向末尾元素下一个位置,操作都是往相反反向,reverse_iterator 为反向迭代器
const_reverse_iterator crbegin();返回反向迭代器,指向末尾元素下一个位置,操作都是往相反反向,并且为常量属性,const_reverse_iterator 常反向迭代器。
reverse_iterator rend();返回反向迭代器,指向开头元素的位置,操作都是往相反反向
const_reverse_iterator cre nd();返回反向迭代器,指向开头元素的位置,操作都是往相反反向,并且为常量属性

迭代器都可以进行++操作。反向迭代器和正向迭代器的区别在于:
对正向迭代器进行++操作时,迭代器会指向容器中的后一个元素;
而对反向迭代器进行++操作时,迭代器会指向容器中的前一个元素。

#include <iostream>
using namespace std;
#include <list>//包含头文件
void printList1(const list<int>& mylist)//形参使用const,避免被修改
{//const_iterator只读迭代器
	for (auto it = mylist.begin(); it != mylist.end(); ++it)
	{
		cout << *it << "|";
	}
	cout << endl;
}
void printList2(const list<int>& mylist)//形参使用const,避免被修改
{//const_iterator只读迭代器
	for (auto it = mylist.rbegin(); it != mylist.rend(); ++it)
	{
		cout << *it << "|";
	}
	cout << endl;
}
void test()
{
	list<int> mylist;
	for (int i = 0; i < 5; i++)
	{
		mylist.push_back(i + 1);//1 2 3 4 5
	}
	printList1(mylist);
	printList2(mylist);
}
int main()
{
	test();
	return 0;
}

在这里插入图片描述

注意:begin函数和cbegin函数都可以返回const_iterator,那么为什么要两个函数呢?
因为begin函数有重载,无法配合auto(自动推导数据类型)使用,所以才多出一个cbegin函数。

list特性操作

函数原型解释
size_t size() const;返回容器的实际大小(已使用的空间)。
bool empty() const;判断容器是否为空。
void clear();清空容器。
void resize(size_t size);把容器的实际大小置为size,如果size<实际大小,会截断多出的部分;如果size>实际大小,则以默认值0填充新位置
void resize(size_t size,const T &value);把容器的实际大小置为size,如果size<实际大小,会截断多出的部分;如果size>实际大小,就用value填充。

实例:特性函数演示

#include <iostream>
using namespace std;
#include <list>//包含头文件
void printList(const list<int>& mylist)//形参使用const,避免被修改
{//const_iterator只读迭代器
	for (list<int>::const_iterator it = mylist.begin(); it != mylist.end(); ++it)
	{
		cout << *it << " ";
	}
	cout << endl;
}
void test()
{
	list<int> mylist;
	for (int i = 0; i < 5; i++)
	{
		mylist.push_back(i + 1);
	}

	cout << "size:" << mylist.size() << endl;//5

	cout << mylist.empty() << endl;//0
	if (mylist.empty())
	{
		cout << "空" << endl;
	}
	else
	{
		cout << "不为空" << endl;
	}

	mylist.resize(3);
	printList(mylist);//1 2 3

	mylist.resize(5);//重新指定容器的长度为num,若容器变长,则以默认值填充新位置。
	printList(mylist);//1 2 3 0 0

	mylist .resize(10, 6);//如果容器变长,也可以用value填充
	printList(mylist);//1 2 3 0 0 6 6 6 6 6 
}
int main()
{
	test();
	return 0;
}

在这里插入图片描述

list元素操作

函数原型解释
T& front();返回第一个元素。
T& back();返回最后一个元素。

list赋值操作

作用:通过重载赋值运算符operator=和成员函数assign(),给已存在的容器赋值,将覆盖容器中原有的内容。

函数原型解释
list assign(beg, end);将[beg, end)区间中的数据拷贝赋值给本身。
void assign(const size_t n, const T& value);将n个elem拷贝赋值给本身。
list& operator=(const list &lst);重载等号操作符,把容器l赋值给当前容器。

实例:赋值操作演示

#include <iostream>
using namespace std;
#include <list>//包含头文件
#include<algorithm>
void printList(const list<int>& mylist)//形参使用const,避免被修改
{//const_iterator只读迭代器
	for (list<int>::const_iterator it = mylist.begin(); it != mylist.end(); ++it)
	{
		cout << *it << " ";
	}
	cout << endl;
}

void test()
{
	list<int> mylist;
	mylist.assign(10, 10);
	printList(mylist);

	list<int> mylist2;
	mylist2.assign(mylist.begin()++, mylist.end()--);
	printList(mylist2);

	cout << mylist.front() << endl;
	cout << mylist.back() << endl;
}
int main()
{
	test();
	return 0;
}

在这里插入图片描述

list的交换、反转、排序、归并操作

函数原型解释
void swap(list<T> &l);把当前容器与l交换,交换的是链表结点的地址。
void reverse();反转链表。
void sort();对容器中的元素进行升序排序。
void sort(_Pr2 _Pred);对容器中的元素进行排序,排序的方法由_Pred决定(二元函数)。
void merge(list< T> &l);采用归并法合并两个已排序的list容器,合并后的list容器仍是有序的。

实例:list的交换、反转、排序、归并操作演示

#include <iostream>
using namespace std;
#include <list>//包含头文件
#include<algorithm>
void printList(const list<int>& mylist)//形参使用const,避免被修改
{//const_iterator只读迭代器
	for (list<int>::const_iterator it = mylist.begin(); it != mylist.end(); ++it)
	{
		cout << *it << " ";
	}
	cout << endl;
}
bool myfunc2(int v1, int v2)
{
	return v1 > v2;
}
void test()
{
	list<int> mylist;
	for (int i = 0; i < 5; i++)
	{
		mylist.push_back(i + 10);//10 11 12 13 14
	}
	list<int> mylist2;
	for (int i = 0; i < 5; i++)
	{
		mylist2.push_back(i);//0 1 2 3 4
	}

	mylist2.swap(mylist); //把当前容器mylist2与mylist交换,交换的是链表结点的地址。
	printList(mylist2);//10 11 12 13 14

	mylist2.reverse();//反转链表

	printList(mylist2);//14 13 12 11 10

	//注意:list容器不能使用sort算法,list容器有自己专属的sort成员函数
	//sort(mylist.begin(), mylist.end());
	
	mylist2.sort(myfunc2);//借助myfunc2函数进行比较,然后sort降序排列
	printList(mylist2);//14 13 12 11 10

	mylist2.sort();//mylist2链表使用sort函数默认升序排列
	printList(mylist2);//10 11 12 13 14

	mylist.sort();//mylist链表使用sort函数默认升序排列
	printList(mylist);//0 1 2 3 4 

	mylist2.merge(mylist); //采用归并法合并两个已排序的list容器,合并后的list容器仍是有序的
	printList(mylist2); //0 1 2 3 4 10 11 12 13 14

}
int main()
{
	test();
	return 0;
}

在这里插入图片描述

list比较操作

函数原型解释
bool operator == (const vector<T> & l) const;重载==运算符,判断当前链表与l是否相等
bool operator != (const vector<T> & l) const;重载!=运算符,判断当前链表与l是否不相等

list插入和删除操作

函数原型解释
void push_front(const T& ele);在容器头部插入一个数据
void push_back(const T& ele);尾部插入元素ele
void pop_front();删除容器第一个数据
void pop_back();删除最后一个元素
iterator insert(iterator pos, const T& value);在指定位置插入一个元素,返回指向插入元素的迭代器。
iterator insert(pos,n,elem);在pos位置插入n个elem数据,返回指向第一个插入元素的迭代器。
iterator insert(iterator pos, iterator first, iterator last);在指定位置插入一个区间的元素,返回指向第一个插入元素的迭代器。
iterator erase(iterator pos);删除指定位置的元素,返回下一个有效的迭代器。
iterator erase(iterator first, iterator last);删除指定区间的元素,返回下一个有效的迭代器。
splice(iterator pos, const vector< T> & l);把另一个链表连接到当前链表pos位置处。
splice(iterator pos, const vector< T> & l, iterator first, iterator last);把另一个链表指定的区间连接到当前链表pos位置处。
splice(iterator pos, const vector< T> & l, iterator first);把另一个链表从first开始的结点连接到当前链表pos位置处。
void remove(const T& value);删除链表中所有值等于value的元素。
void remove_if(_Pr1 _Pred);删除链表中满足条件的元素,参数_Pred是一元函数。
void unique();删除链表中相邻的重复元素,只保留一个。

list插入和删除操作演示:

#include <iostream>
using namespace std;
#include <vector>
#include <list>//包含头文件
void printList(const list<int>& mylist)//形参使用const,避免被修改
{//const_iterator只读迭代器
	for (list<int>::const_iterator it = mylist.begin(); it != mylist.end(); ++it)
	{
		cout << *it << " ";
	}
	cout << endl;
}
bool myfunc(int val)
{
	return val > 300;
}
void test()
{
	list<int> mylist;
	mylist.push_back(10);//在容器尾部插入一个数据
	mylist.push_back(20);
	mylist.push_back(30);
	mylist.push_back(40);
	mylist.push_back(50);
	
	mylist.push_front(100);//在容器头部插入一个数据
	mylist.push_front(200);
	mylist.push_front(300);
	mylist.push_front(400);

	printList(mylist);//400 300 200 100 10 20 30 40 50
	cout << "------------------" << endl;

	list<int>::const_iterator it = mylist.insert(mylist.begin(), 2, 0);//在pos位置插入n个elem数据
	cout << *it << endl;//返回指向第一个插入元素的迭代器。
	cout << "------------------" << endl;

	vector<int> v;
	v.push_back(1000);
	v.push_back(2000);
	v.push_back(3000);

	mylist.insert(mylist.begin(), v.begin(), v.end()); //在指定位置插入一个区间的元素,返回指向第一个插入元素的迭代器
	printList(mylist);//1000 2000 3000 400 300 200 100 10 20 30 40 50
	cout << "------------------" << endl;

	mylist.erase(mylist.begin());//删除第一个元素
	printList(mylist); //2000 3000 400 300 200 100 10 20 30 40 50
	cout << "------------------" << endl;

	list<int> mylist2(6,6);

	mylist.splice(mylist.end(),mylist2);//将mylist2链接到mylist后
	printList(mylist);//2000 3000 400 300 200 100 10 20 30 40 50 6 6 6 6 6 6
	cout << "------------------" << endl;

	mylist.remove(300); //删除链表中所有值等于300的元素
	printList(mylist);//2000 3000 400 200 100 10 20 30 40 50 6 6 6 6 6 6
	cout << "------------------" << endl;

	mylist.remove_if(myfunc);//删除链表中所有值大于300的元素
	printList(mylist);// 200 100 10 20 30 40 50 6 6 6 6 6 6
	cout << "------------------" << endl;
}
int main()
{
	test();
	return 0;
}

在这里插入图片描述

  • 58
    点赞
  • 60
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 74
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 74
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿标de杂货铺

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值