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

C++STL之list

🌟🌟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) 使用迭代器来构造
cpp 复制代码
#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.迭代器

list iterator/reverse_iterator
begin()+end() 双向迭代器
rbegin()+rend() 反向迭代器
cpp 复制代码
#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;
}
cpp 复制代码
#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)为反向迭代器,对迭代器执行++操作,迭代器向前移动

因为是双向迭代器,因此还可以使用- -

cpp 复制代码
#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() 链表是否为空
cpp 复制代码
#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() 获取第一个元素的值
cpp 复制代码
#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) 交换两个链表
cpp 复制代码
#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;
}

再来看看插入和删除

cpp 复制代码
#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()

cpp 复制代码
#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的迭代器是经过封装的,但本质还是结点

再来看一下下面的一个比较巧妙的用法

cpp 复制代码
#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++的相关知识,干货满满,如果觉得博主写的还不错的话,希望各位小伙伴不要吝啬手中的三连哦!你们的支持是博主坚持创作的动力!💪💪

相关推荐
MiyamiKK574 分钟前
leetcode_字符串 409. 最长回文串
数据结构·算法·leetcode
Biomamba生信基地4 分钟前
R语言基础| 回归分析
开发语言·回归·r语言
黑客-雨19 分钟前
从零开始:如何用Python训练一个AI模型(超详细教程)非常详细收藏我这一篇就够了!
开发语言·人工智能·python·大模型·ai产品经理·大模型学习·大模型入门
Pandaconda23 分钟前
【Golang 面试题】每日 3 题(三十九)
开发语言·经验分享·笔记·后端·面试·golang·go
半盏茶香24 分钟前
扬帆数据结构算法之雅舟航程,漫步C++幽谷——LeetCode刷题之移除链表元素、反转链表、找中间节点、合并有序链表、链表的回文结构
数据结构·c++·算法
加油,旭杏27 分钟前
【go语言】变量和常量
服务器·开发语言·golang
行路见知28 分钟前
3.3 Go 返回值详解
开发语言·golang
xcLeigh31 分钟前
WPF实战案例 | C# WPF实现大学选课系统
开发语言·c#·wpf
哎呦,帅小伙哦32 分钟前
Effective C++ 规则41:了解隐式接口和编译期多态
c++·effective c++
NoneCoder41 分钟前
JavaScript系列(38)-- WebRTC技术详解
开发语言·javascript·webrtc