当前位置: 首页 > article >正文

C++STL之list(用法超详解)

C++STL之list

  • 1.list基本介绍
  • 2.构造函数
  • 3.迭代器
  • 4.空间成员函数
  • 5.元素获取成员函数
  • 6.元素操作成员函数
  • 7.迭代器失效问题
  • 8.list和vector的对比

🌟🌟hello,各位读者大大们你们好呀🌟🌟
🚀🚀系列专栏:【C++的学习】
📝📝本篇内容:list基本介绍;构造函数;迭代器;空间成员函数;元素获取成员函数;元素操作成员函数;迭代器失效问题;list和vector的对比
⬆⬆⬆⬆上一篇:C++模拟实现string(图解+超详版)
💖💖作者简介:轩情吖,请多多指教(> •̀֊•́ ) ̖́-

1.list基本介绍

在STL中也有对list的实现,它是一个带头双向循环链表,底层是一个双向迭代器。forward_list是单链表,它底层只是一个单向迭代器。与其他的序列式容器相比(array,vector,deque),list通常在任意位置进行插入、移除元素的执行效率更好。但是他也有缺点,与其他序列式容器相比,list和forward_list最大的缺陷是不支持任意位置的随机访问,比如:要访问list的第6个元素,必须从已知的位置(比如头部或者尾部)迭代到该位置,在这段位置上迭代需要线性的时间开销;list还需要一些额外的空间,以保存每个节点的相关联信息。
在这里插入图片描述

2.构造函数

list构造函数
list默认构造函数
list(size_type n, const value_type& val = value_type())构造n个值为val的元素
list (const list& x)拷贝构造
list (InputIterator first, InputIterator last)使用迭代器来构造
#include <list>
#include <iostream>
using namespace std;
int main()
{
	//默认构造
	list<int> lt;

	//拷贝构造
	list<int> lt1(lt);

	//5个为20
	list<int> lt2(5, 20);
	for (auto& e : lt2)
	{
		cout << e << " ";
	}
	cout << endl;

	//使用迭代器构造
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	list<int> lt3(arr, arr + 10);
	for (auto& e : lt3)
	{
		cout << e << " ";
	}
	cout << endl;

	return 0;
}

在这里插入图片描述

3.迭代器

listiterator/reverse_iterator
begin()+end()双向迭代器
rbegin()+rend()反向迭代器
#include <list>
#include <iostream>
using namespace std;
int main()
{
	list<int> lt(5, 20);
	//迭代器
	list<int>::iterator it=lt.begin();
	while (it != lt.end())
	{
		cout << *it << " ";
		it++;
	}

	return 0;
}
#include <list>
#include <iostream>
using namespace std;
int main()
{
	list<int> lt{ 1,2,3,3,4,5,6,7,8,9,10 };
	//反向迭代器
	list<int>::reverse_iterator rit = lt.rbegin();
	while (rit != lt.rend())
	{
		cout << *rit << " ";
		rit++;
	}

	return 0;
}

begin与end为正向迭代器,对迭代器执行++操作,迭代器向后移动
rbegin(end)与rend(begin)为反向迭代器,对迭代器执行++操作,迭代器向前移动
因为是双向迭代器,因此还可以使用- -

#include <list>
#include <iostream>
using namespace std;
int main()
{
	list<int> lt={1,2,3,4,5,6,7,8,9,10};
	list<int>::iterator it = lt.end();
	while (it != lt.begin())
	{
		--it;//这边得先--再使用,因为end()指向的是最后一个元素的下一个
		cout <<*it << " ";
	}


	return 0;
}

4.空间成员函数

list空间函数
size()链表大小
empty()链表是否为空
#include <iostream>
#include <list>
using namespace std;
int main()
{
	list<int> lt{1, 2, 3, 4, 5, 6, 7};
	//大小
	cout << lt.size() << endl;
	//是否为空
	cout << lt.empty() << endl;

	return 0;
}

5.元素获取成员函数

list元素获取函数
back()获取最后一个元素的值
front()获取第一个元素的值
#include <iostream>
#include <list>
using namespace std;
int main()
{
	list<int> lt{1, 2, 3, 4, 5, 6, 7};
	cout << "The first element:";
	cout << lt.front() << endl;
	cout << "The end elemeent:";
	cout << lt.back() << endl;

	return 0;
}

在这里插入图片描述

6.元素操作成员函数

list元素操作函数
push_back( (const value_type& val))尾插
push_front( (const value_type& val))头插
pop_front()头删
pop_back()尾删
iterator insert (iterator position, const value_type& val)在positon位置插入val
void insert (iterator position, size_type n, const value_type& val)在position位置插入n个val
iterator erase (iterator position)删除position位置的元素
iterator erase (iterator first, iterator last)以迭代器的方式删除[first,last)的元素
clear()清空链表
swap(list& lt)交换两个链表
#include <iostream>
#include <list>
using namespace std;
int main()
{
	list<int> lt;
	//尾插
	lt.push_back(10);
	lt.push_back(11);
	lt.push_back(12);
	for (auto& e : lt)
	{
		cout << e << " ";
	}
	cout << endl;

	//头插
	lt.push_front(9);
	lt.push_front(8);
	lt.push_front(7);
	for (auto& e : lt)
	{
		cout << e << " ";
	}
	cout << endl;

	//头删
	lt.pop_front();
	for (auto& e : lt)
	{
		cout << e << " ";
	}
	cout << endl;

	//尾删
	lt.pop_back();
	for (auto& e : lt)
	{
		cout << e << " ";
	}
	cout << endl;

	return 0;
}

在这里插入图片描述

再来看看插入和删除

#include <iostream>
#include <list>
#include <algorithm>
using namespace std;
int main()
{
	list<int> lt;
	lt.push_back(10);
	lt.push_back(11);
	lt.push_back(12);
	lt.push_back(13);
	cout << "初始元素:";
	for (auto& e : lt)
	{
		cout << e << " ";
	}
	cout << endl;
	
	//insert
	list<int>::iterator it=find(lt.begin(), lt.end(), 11);
	lt.insert(it, 7);
	cout << "insert之后:";
	for (auto& e : lt)
	{
		cout << e << " ";
	}
	cout << endl;

	//erase(iterator position)
	auto it1 = find(lt.begin(), lt.end(), 12);
	lt.erase(it1);
	cout << "erase之后:";
	for (auto& e : lt)
	{
		cout << e << " ";
	}
	cout << endl;

	//erase(iterator first,iterator last)
	lt.erase(lt.begin(), lt.end());
	cout << "insert之后:";
	for (auto& e : lt)
	{
		cout << e << " ";
	}
	cout << endl;

	return 0;
}

在这里插入图片描述

swap()和clear()

#include <iostream>
#include <list>
using namespace std;
int main()
{
	list<int> lt;
	lt.push_back(1);
	lt.push_back(2);
	lt.push_back(3);
	lt.push_back(4);
	lt.push_back(5);
	cout << "初始元素:";
	for (auto& e : lt)
	{
		cout << e<<" ";
	}
	cout << endl;

	//交换swap
	list<int> lt1;
	lt.swap(lt1);
	cout << "lt和默认构造lt1交换后的元素:";
	for (auto& e : lt)//没有元素
	{
		cout << e<<" ";
	}
	cout << endl;
	cout << "lt1的元素:";
	for (auto& e : lt1)
	{
		cout << e << " ";
	}
	cout << endl;

	//清空lt1
	lt1.clear();
	cout << "lt1清空元素后:";
	for (auto& e : lt1)//没有元素
	{
		cout << e << " ";
	}
	cout << endl;

	return 0;
}

在这里插入图片描述

7.迭代器失效问题

在前面咱们讲的vector时,我们也提到过迭代器失效问题,我们的list也会有这个问题,但是有区别。我们的list因为是一个个的结点,因此你进行插入的话并不会造成原来的迭代器失效,但是如果是删除呢?这就会有问题,因为当你删除一个结点时,肯定会释放空间,一旦释放空间,那么这个结点中的内容就已经无效了。当再次使用迭代器进行++时,就类似于访问野指针一样,导致崩溃。删除时的迭代器失效仅仅是被删除的迭代器,其他迭代器不会受任何影响。具体看我下一篇博客的list模拟实现中的迭代器实现可以更好的理解,list的迭代器是经过封装的,但本质还是结点
在这里插入图片描述
再来看一下下面的一个比较巧妙的用法

#include <iostream>
#include <list>
using namespace std;
int main()
{
	list<int> lt;
	lt.push_back(1);
	lt.push_back(2);
	lt.push_back(3);
	lt.push_back(4);
	lt.push_back(5);
	auto it = lt.begin();
	//一个个进行删除
	while (it!=lt.end())
	{
		//这边如果不用这种写法,就得接收返回值
		lt.erase(it++);//后置++是先使用后+1,因此在实现中,返回的其实是没有+1前的值,it迭代器已经+1了
		//it=lt.erase(it);
	}

	if (lt.empty())
	{
		cout << "list is empty"<<endl;
	}
	
	return 0;
}

在这里插入图片描述

8.list和vector的对比

在这里插入图片描述

🌸🌸C++STL之list的知识大概就讲到这里啦,博主后续会继续更新更多C++的相关知识,干货满满,如果觉得博主写的还不错的话,希望各位小伙伴不要吝啬手中的三连哦!你们的支持是博主坚持创作的动力!💪💪


http://www.kler.cn/a/442638.html

相关文章:

  • 在Linux系统中无网络安装Nginx并配置负载均衡
  • C++中的STL
  • 【入门级】计算机网络学习
  • 【Redis】初识Redis
  • vue 与 vue-json-viewer 实现 JSON 数据可视化
  • 论文笔记(四十七)Diffusion policy: Visuomotor policy learning via action diffusion(下)
  • 一款可以替代Navicat的数据库管理工具
  • java: 无效的目标发行版: 9或警告: 源发行版 9 需要目标发行版 9
  • android liveData更新UI数据
  • google guava 库 最佳实践 学习指南 学习实用示例
  • “智联实验舱”:基于 SSM 和 Vue 的 WEB 开放性实验室管控系统
  • 【第一篇】 数据库管理工具概述
  • Vue3动态表单实现
  • 游戏关卡分析:荒野大镖客2雪山终战
  • 探索高级 SQL 技巧:提升数据库操作效率
  • MyBatis学习笔记:进阶知识2
  • World-Grounded Human Motion Recovery via Gravity-View Coordinates
  • Unity NTPComponent应用, 实现一个无后端高效获取网络时间的组件
  • 云计算笔记
  • 基于AI对话生成剧情AVG游戏
  • 数据结构之顺序存储二叉树
  • kubernetes学习-应用程序的生命周期管理
  • 【从零开始入门unity游戏开发之——C#篇11】一个标准 C# 程序介绍、新的值类型——枚举
  • SEO初学者-SEO基础
  • 《云原生安全攻防》-- K8s安全框架:认证、鉴权与准入控制
  • 在JVM(Java虚拟机)中,PC寄存器(Program Counter Register)扮演着至关重要的角色。