第九层(7):STL之list

🎉welcome🎉
✒️博主介绍:一名大一的智能制造专业学生,在学习C/C++的路上会越走越远,后面不定期更新有关C/C++语法,数据结构,算法,Linux,ue5使用,制作游戏的心得,和大家一起共同成长。
✈️C++专栏:C++爬塔日记
😘博客制作不易,👍点赞+⭐收藏+➕关注

前情回顾

在上一块石碑中,我学到了queue,同时下一块石碑也显露出来…

list

概念

  • list可以将数据链式存储,list也就是链表,链表是由一系列的节点组成,节点是内部有两块区域,一个是存放下一个节点地址的指针域,一个是存放数据的数据域,链表可以对任意位置进行快速的插入和删除,但是因为链表不是一块连续的空间,所以遍历的速度慢于数组,并且占用空间比数组要大,list的本质就是一个双向循环链表,双向循环列表指的就是,第一个节点记录着最后的位置,最后一个节点记录第一个节点的位置

在这里插入图片描述

  • 由于链表的储存方法不是连续空间,所以list的迭代器只支持前移和后移,属于双向迭代器,不能随机访问

优缺点

  • 优点:
    1. 采用动态存储分配,不会造成内存的浪费和溢出
    2. list的插入和删除十分方便,只需要修改指针就可以,不需要移动内部的大量数据
    3. list的插入和删除不会造成原有的迭代器失效,而vector不行,因为vector在插入扩展的时候,会找一片新空间将数据拷贝过去,
  • 缺点:
    1. 相比较数组而言,链表所占用的空间较大,遍历消耗的额外时间较多

构造函数

  • list中的构造函数与vector一样,有四个构造函数
list< T >;//;默认构造函数
list(beg,end);//将迭代器beg到end之间的数据拷贝到本身
list(size_t n,T elem);//将n个elem赋值给本身
list(const list &l);//将l的元素拷贝到本身

使用:

#include<iostream>
#include<list>
using namespace std;

void print(list<int>& l)
{
	for (list<int>::iterator b=l.begin(); b != l.end(); b++)
	{
		cout << *b << " ";
	}
	cout << endl;
}
void test1()
{
	list<int> l;
	list<int> l1(10, 1);
	print(l1);
	list<int>l2(l1);
	print(l2);
	list <int>l3(l1.begin(), l1.end());
	print(l3);
}
int main()
{
	test1();
	return 0;
}

在这里插入图片描述

赋值函数

  • list中的赋值操作与vector中也是一样的,有三种
list& operator=(const list &l);//操作符重载
assign(beg,end);//将迭代器beg到end的数据拷贝到本身
assign(int n,T elem);//将n个elem拷贝到本身

使用:

#include<iostream>
#include<list>
using namespace std;

void print(list<int>& l)
{
	for (list<int>::iterator b=l.begin(); b != l.end(); b++)
	{
		cout << *b << " ";
	}
	cout << endl;
}
void test1()
{
	list<int> l(10, 1);
	print(l);
	list<int> l1;
	l1 = l;
	print(l1);
	list<int> l2;
	l2.assign(l1.begin(),l1.end());
	print(l2);
	list<int> l3;
	l3.assign(10, 2);
	print(l3);
}
int main()
{
	test1();
	return 0;
}

在这里插入图片描述

交换函数

  • 与vector一样,可以利用swap函数进行交换
swap(list< T > &l);//将l的数据和本身进行交换

使用:

#include<iostream>
#include<list>
using namespace std;

void print(list<int>& l)
{
	for (list<int>::iterator b=l.begin(); b != l.end(); b++)
	{
		cout << *b << " ";
	}
	cout << endl;
}
void test1()
{
	cout << "交换前" << endl;
	list<int> l(10, 1);
	print(l);
	list<int> l1;
	l1.assign(10, 2);
	print(l1);
	cout << "交换后" << endl;
	l.swap(l1);
	print(l);
	print(l1);
}
int main()
{
	test1();
	return 0;
}

在这里插入图片描述

容器和大小操作

  • list比vector少一个容器大小,因为list的空间不是连续的,数据存放方式也与vector不同,有多少元素大小就多少,和vector不一样,所以不需要
size();//返回容器内元素个数
empty();//判断容器是否为空,为空返回真
resize(size_t num);///可以重新指定容器的容量,容量为num,若容器变长,则变长的部分全部补0,若变短,则将超出的部分全部删除
reszie(size_t num,T elem);//可以重新指定容器的容量,容量为num,若容器变长,则变长的部分全部补elem,若变短,则将超出的部分全部删除

使用:

#include<iostream>
#include<list>
using namespace std;

void print(list<int>& l)
{
	for (list<int>::iterator b=l.begin(); b != l.end(); b++)
	{
		cout << *b << " ";
	}
	cout << endl;
}
void test1()
{
	list<int> l;
	if (l.empty())
	{
		cout << "l为空" << endl;
	}
	cout << l.size() << endl;
	l.assign(10, 1);
	print(l);
	l.resize(11);
	print(l);
	l.resize(15, 1);
	print(l);
}
int main()
{
	test1();
	return 0;
}

在这里插入图片描述

插入操作

  • list中,有五种插入操作,可以从头部插入,从尾部插入,还有insert的三个重载版本
push_front(T elem);//在头部插入elem
push_end(T elem);//在尾部插入elem
insert(pos,T elem);//在pos的位置插入一个elem,返回新数据的位置
insert(pos, size_t n,T elem);//在pos位置插入n个elem
insert(pos,beg,end);//在pos位置插入迭代器beg到end的数据

使用:

#include<iostream>
#include<list>
using namespace std;

void print(list<int>& l)
{
	for (list<int>::iterator b=l.begin(); b != l.end(); b++)
	{
		cout << *b << " ";
	}
	cout << endl;
}
void test1()
{
	list<int> l;
	l.push_back(2);
	print(l);
	l.push_front(1);
	print(l);
	l.insert(l.end(), 3);
	print(l);
	l.insert(l.begin(), 1,0);
	print(l);
	list<int>::iterator b = l.begin();
	b++;
	l.insert(b, l.begin(), l.end());
	print(l);
}
int main()
{
	test1();
	return 0;
}

在这里插入图片描述

删除操作

  • 删除操作有六个,向比较vector多了头部的删除,和一个删除一样元素的删除
pop_back();//删除尾部元素
pop_front();//删除头部元素
clear();//删除全部元素
erase(beg,end);//删除迭代器beg到end之间的数据
erase(pos);//删除迭代器pos位置的数据,返回下一个元素的位置
remove(T elem);//删除容器中所有的elem

使用:

#include<iostream>
#include<list>
using namespace std;

void print(list<int>& l)
{
	for (list<int>::iterator b=l.begin(); b != l.end(); b++)
	{
		cout << *b << " ";
	}
	cout << endl;
}
void test1()
{
	list<int> l;
	for (int i = 0; i < 10; i++)
	{
		l.push_back(i);
		l.push_back(i);
	}
	print(l);
	l.pop_back();
	print(l);
	l.pop_front();
	print(l);
	list<int>::iterator b = l.begin();
	b++; b++; b++;
	l.erase(b);
	print(l);
	list<int>::iterator b1 = l.begin();
	b1++; b1++; b1++;
	l.erase(b1, l.end());
	print(l);
	l.remove(1);
	print(l);
	l.clear();
	print(l);
}
int main()
{
	test1();
	return 0;
}

在这里插入图片描述

单个数据访问

  • 因为在list中空间不是连续的,同时,list的迭代器也不支持随机访问,所以对于list来说[ ]和at是不适用于list的,可以利用迭代器++或者–来访问其他元素
front();//返回第一个元素
back();//返回最后一个元素

使用:

#include<iostream>
#include<list>
using namespace std;

void print(list<int>& l)
{
	for (list<int>::iterator b=l.begin(); b != l.end(); b++)
	{
		cout << *b << " ";
	}
	cout << endl;
}
void test1()
{
	list<int> l;
	for (int i = 0; i < 10; i++)
	{
		l.push_back(i);
	}
	print(l);
	cout << l.front() << endl;
	cout << l.back() << endl;
}
int main()
{
	test1();
	return 0;
}

在这里插入图片描述

反转操作

  • 在list中可以反转链表,就是让链表中所有元素交换位置,后面的与前面的交换。
reverse();//反转链表

使用:

#include<iostream>
#include<list>
using namespace std;

void print(list<int>& l)
{
	for (list<int>::iterator b=l.begin(); b != l.end(); b++)
	{
		cout << *b << " ";
	}
	cout << endl;
}
void test1()
{
	list<int> l;
	for (int i = 0; i < 10; i++)
	{
		l.push_back(i);
	}
	cout << "反转前" << endl;
	print(l);
	cout << "反转后" << endl;
	l.reverse();
	print(l);
}
int main()
{
	test1();
	return 0;
}

在这里插入图片描述

排序

  • 在容器当中,可以使用一个算法函数来对容器内的数据进行一个排序,默认从小到大,但是是对于支持随机访问的迭代器,可以使用标准算法,对于list这种不支持随机访问的迭代器,是不可以用标准算法的,只能用类内的算法
sort();//排序

使用:

#include<iostream>
#include<list>
using namespace std;

void print(list<int>& l)
{
	for (list<int>::iterator b=l.begin(); b != l.end(); b++)
	{
		cout << *b << " ";
	}
	cout << endl;
}
void test1()
{
	list<int> l;
	for (int i = 9; i >=0; i--)
	{
		l.push_back(i);
	}
	print(l);
	l.sort();
	print(l);
}
int main()
{
	test1();
	return 0;
}

在这里插入图片描述

  • 那想从大到小排呢?这个时候需要一个函数,函数返回类型为bool,内部可以让传参的两个参数进行比较,任何前者大于后者,返回真,如果小于返回假,返回假就会进行交换
#include<iostream>
#include<list>
using namespace std;

void print(list<int>& l)
{
	for (list<int>::iterator b=l.begin(); b != l.end(); b++)
	{
		cout << *b << " ";
	}
	cout << endl;
}
bool com(int a, int b)
{
	return a > b;//可以简化成这样,返回的是a>b的结果,如果结果是对的,不进行交换,如果不对,进行交换
}
void test1()
{
	list<int> l;
	for (int i = 0; i < 10; i++)
	{
		l.push_back(i);
	}
	print(l);
	l.sort(com);
	print(l);
}
int main()
{
	test1();
	return 0;
}

在这里插入图片描述

下一座石碑

  • 这座石碑倒下了,露出了下一座石碑…

😘预知后事如何,关注新专栏,和我一起征服C++这座巨塔
🚀专栏:C++爬塔日记
🙉都看到这里了,留下你们的👍点赞+⭐收藏+📋评论吧🙉

  • 21
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 27
    评论
评论 27
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

封心锁爱的前夫哥

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

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

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

打赏作者

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

抵扣说明:

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

余额充值