[C++初阶]list类的初步理解

news2024/9/29 23:38:25

一、标准库的list类

list的底层是一个带哨兵位的双向循环链表结构
对比forward_list的单链表结构,list的迭代器是一个双向迭代器
与vector等顺序结构的容器相比,list在任意位置进行插入删除的效率更好,但是不支持任意位置的随机访问
list是一个模板类,在使用的时候我们需要给出元素的类型

使用list类时,需要包含头文件<list>

二、list类的常用接口

1.常用的构造函数

1.默认构造函数,构造一个空的链表

list();

例如:

void test()
{
	list<int> lt;
}

2.构造一个list对象并用n个val初始化

list(size_type n, const value_type& val =  value_type());

例如:

void test()
{
	list<int> lt(3, 1);
	for (auto i : lt)
	{
		cout << i << " ";
	}
}

运行结果:

3.list类的拷贝构造函数

list(const list& x); 

例如:

void test()
{
	list<int> lt(3, 1);
	list<int> lt1(lt);
	for (auto i : lt1)
	{
		cout << i << " ";
	}
}

运行结果:

4.使用迭代器的初始化构造

Template<class InputIterator>

list(InputIterator first, InputIterator last);

例如:

void test()
{
	list<int> lt(3, 1);
	list<int> lt1(lt.begin(), lt.end());
	for (auto i : lt1)
	{
		cout << i << " ";
	}
}

运行结果:

2.常用的容量接口

还是老几样,我这里一块讲一讲吧。

1.size,empty,max_size,resize

size:返回链表容器中的元素数。

size_type size() const;

empty:返回列表容器是否为空(即其大小是否为 0)。
(注意:此函数不会以任何方式修改容器。若要清除链表容器的内容,请参阅 list::clear。)

bool empty() const;

max_size(不常用):返回链表容器可以容纳的最大元素数。
(由于已知的系统或库实现限制,这是容器可以达到的最大潜在大小,但绝不能保证容器能够达到该大小:在达到该大小之前,它仍然可能无法在任何时候分配存储。)

size_type max_size() const;

resize:调整容器的大小,使其包含 n 个元素。
如果 n 小于当前容器大小,则内容将减少到其前 n 个元素,删除超出(并销毁它们)的元素。
如果 n 大于当前容器大小,则通过在末尾插入所需数量的元素来扩展内容,以达到 n 的大小。如果指定了 val,则新元素将初始化为 val 的副本,否则,它们将进行值初始化。
(请注意,此函数通过插入或擦除容器中的元素来更改容器的实际内容。)

void resize (size_type n, value_type val = value_type());

例如:

​
void test()
{
	list<int> lt(3, 1);
	/*list<int> lt1(lt);*/
	list<int> lt1(lt.begin(), lt.end());
	list<int> lt2;
	cout << lt1.size() <<endl;
	cout << lt1.empty() <<endl;
	cout << lt2.empty() <<endl;
	lt1.resize(10);
	cout << lt1.size() << endl;
	for (auto i : lt1)
	{
		cout << i << " ";
	}
}

​

运行结果:

3. 常用的访问与遍历

1.迭代器

iterator begin();

const_iterator begin() const;

iterator end();

const_iterator end() const;

迭代器:用于获取链表中第一个节点的位置和最后一个节点的下一个位置(即哨兵位)

例如:

void test()
{
	list<int> lt(5, 2);
	list<int> ::iterator it = lt.begin();
	while (it != lt.end())
	{
		cout << *it << " ";
		++it;
	}
}

运行结果:

2.反向迭代器

reverse_iterator rbegin();

const_reverse_iterator rbegin() const;

reverse_iterator rend();

const_reverse_iterator rend() const;

反向迭代器,rbegin获取容器中最后一个节点的位置,rend获取容器中哨兵位的位置

void test()
{
	list<int> lt = { 1,23,4,4,5,2 };
	list<int> ::reverse_iterator rit = lt.rbegin();
	while (rit != lt.rend())
	{
		cout << *rit << " ";
		++rit;
	}
}

运行结果:

注意:反向迭代器rit也要用++而不是--

3.front和back

front:

reference front();

const_reference front() const;

返回链表中第一个节点存储的数据的引用

back:

reference back();

const_reference back() const;

返回链表中最后一个节点存储的数据的引用

例如:

void test()
{
	list<int> lt = {213123,123,34524,213};
	cout << lt.front() << endl;
	cout << lt.back() << endl;

}

运行结果:

4.list的增删查改

1)push_front和pop_front

push_front叫头插,从链表头部插入一个元素

void push_front(const value_type& val);

pop_front叫头删,从链表头部删除一个元素

void pop_front();

void pop_front();

例如:

void test()
{
	list<int> lt = {213123,123,34524,213};
	cout << lt.front() << endl;
	lt.push_front(21345);
	cout << lt.front() << endl;
	lt.pop_front();
	cout << lt.front() << endl;
}

运行结果:

2) push_back和pop_back

push_back叫尾插,从链表尾部插入一个元素

void push_back(const value_type& val);

pop_back叫尾删,从链表尾部删除一个元素

void pop_back();

例如:

void test()
{
	list<int> lt = {213123,123,34524,213};
	cout << lt.back() << endl;
	lt.push_back(21345);
	cout << lt.back() << endl;
	lt.pop_back();
	cout << lt.back() << endl;
}

运行结果:

3) find

template <class InputIterator, class T>

InputIterator find(InputIterator first, InputIterator last, const T& val);

在两个迭代器区间寻找val并返回其所在处的迭代器

例如:

void test()
{
	list<int> lt;
	for (int i = 0; i < 3; i++)
	{
		lt.push_back(i);
	}
	list<int>::iterator pos = find(lt.begin(), lt.end(), 1);
	*pos = 114514;
	for (auto i : lt)
	{
		cout << i << " ";
	}
}

运行结果:

注意:该函数并非list的成员函数,是标准库中的函数,多个容器共用该find函数

可以看到,我们可以直接对list的迭代器进行解引用并修改其内容,但是迭代器不应该指向节点吗?为什么对其解引用能修改数据呢?

实际上list的迭代器并不是用原生态指针进行模拟实现的,需要进行底层的封装,这里会在list的模拟实现的源代码中体现。

4)insert

iterator insert(iterator position, const value_type& val);

void insert(iterator position, size_type n, const value_type& val);

————————————————————————————————————————

template<class InputIterator>

void insert(iterator position, InputIterator first, InputIterator last);

在position位置的前面插入一个或多个元素

例如:

void test()
{
	list<int> lt;
	for (int i = 0; i < 3; i++)
	{
		lt.push_back(i);
	}
	list<int>::iterator pos = find(lt.begin(), lt.end(), 1);
	lt.insert(pos, 8848);
	for (auto i : lt)
	{
		cout << i << " ";
	}
}

运行结果:

细心的同学可能已经发现了,list的insert操作是不会导致迭代器失效的,因为pos指向的节点不变,相对位置也不变。

但是list的删除操作一定会导致迭代器失效,并且失效的只是指向被删除节点的迭代器,其他迭代器不会受到影响。

5) erase

iterator erase(iterator position);

iterator erase(iterator first, iterator last);

删除position位置的元素或者 [first,last) 区间的所有元素

例如:

void test()
{
	list<int> lt;
	for (int i = 0; i < 3; i++)
	{
		lt.push_back(i);
	}
	list<int>::iterator pos = find(lt.begin(), lt.end(), 1);
	lt.erase(lt.begin());
	for (auto i : lt)
	{
		cout << i << " ";
	}
}

运行结果:

void test()
{
	list<int> lt;
	for (int i = 0; i < 3; i++)
	{
		lt.push_back(i);
	}
	list<int>::iterator pos = find(lt.begin(), lt.end(), 2);
	lt.erase(lt.begin(),pos);
	for (auto i : lt)
	{
		cout << i << " ";
	}
}

运行结果:

6) swap

void swap(vector& x);

交换两个list对象

例如:

void test()
{
	list<int> lt;
	list<int> lt2(6, 12);
	for (int i = 0; i < 10; i++)
	{
		lt.push_back(i);
	}
	lt.swap(lt2);
	for (auto i : lt2)
	{
		cout << i << " ";
	}
	cout << endl;
}

运行结果:

7)assign

template <class InputIterator>

void assign(InputIterator first, InputIterator last);

void assign(size_type n, const value_type& val);

为list指定新内容,替换其当前内容并修改节点个数

例如:

void test()
{
	list<int> lt;
	for (int i = 0; i < 10; i++)
	{
		lt.push_back(i);
	}
	lt.assign(4, 0);
	for (auto i : lt)
	{
		cout << i << " ";
	}
}

运行结果:

8)clear

void clear();

删除链表所有节点

例如:

void test()
{
	list<int> lt;
	for (int i = 0; i < 10; i++)
	{
		lt.push_back(i);
	}
	lt.clear();
	cout << lt.size() << endl;
}

运行结果:

5.list的顺序修改接口

(1)sort

void sort();

template<class Compare>

void sort(Compare comp);

list由于结构的特殊性,是无法使用标准库中的sort函数的,因为迭代器无法进行相减的操作

并且在C++文档中,我们可以看到标准库中的sort也限定了迭代器的类型必须是可以进行随机访问(RandomAccess)的

default (1)	
template <class RandomAccessIterator>
  void sort (RandomAccessIterator first, RandomAccessIterator last);
custom (2)	
template <class RandomAccessIterator, class Compare>
  void sort (RandomAccessIterator first, RandomAccessIterator last, Compare comp);

迭代器有几个功能分类:

  • 单向迭代器,只能进行++
  • 双向迭代器,可以++和--
  • 随机迭代器,可以++,--,+和-

但是list的sort函数也是没什么必要的,因为直接对链表排序的效率比拷贝到vector进行排序再拷贝回链表要慢的多。

(2)reverse

template <class BidirectionalIterator>
  void reverse (BidirectionalIterator first, BidirectionalIterator last);

对链表进行逆置

例如:

void test()
{
	list<int> lt;
	for (int i = 0; i < 10; i++)
	{
		lt.push_back(i);
	}
	for (auto i : lt)
	{
		cout << i << " ";
	}
	cout << endl;
	lt.reverse();
	for (auto i : lt)
	{
		cout << i << " ";
	}
	cout << endl;

}

运行结果:


如有错误,欢迎指正。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1913591.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

最新Wireshark查看包中gzip内容

虽然是很简单的事情&#xff0c;但是网上查到的查看gzip内容的方法基本都是保存成zip文件&#xff0c;然后进行二进制处理。 其实现在最新版本的Wireshark已经支持获取gzip内容了。 选中HTTP协议&#xff0c;右键选择[追踪流]->[HTTP Stream] 在弹出窗口中&#xff0c;已…

图像分割SAM辅助标注工具,可调用SAM等大模型(保姆级教程)

SAM等模型通过先进的深度学习技术&#xff0c;实现了高效、精准的图像自动化标注。这不仅显著降低了人工标注的工作量和成本&#xff0c;提高了标注效率和精度&#xff0c;还为各个领域的研究和应用提供了强大的技术支持。随着SAM等模型的不断完善和应用&#xff0c;自动化标注…

一个项目学习Vue3---Vue3中自带的事件

1. .stop 阻止事件继续传播&#xff0c;即防止事件冒泡到父元素。 <div click.stop"handleClick">点击我</div> 2. .prevent 阻止事件的默认行为&#xff0c;比如阻止表单提交时的页面刷新。 <form submit.prevent"handleSubmit">阻…

springboot美食分享平台-计算机毕业设计源码45429

基于Web美食分享平台的系统设计与实现 摘 要 本研究基于Spring Boot框架&#xff0c;设计并实现了一个Web美食分享平台&#xff0c;旨在为用户提供一个交流分享美食体验的社区平台。该平台涵盖了用户注册登录、美食制作方法分享发布、点赞评论互动等功能模块&#xff0c;致力于…

递归(四)—— 初识暴力递归之“打印字符串的全排列”

题目1&#xff1a;序列打印一个字符串的全排列 题目分析&#xff1a;结合一实例来理解题目&#xff0c;str “abc”的全排列就是所求得的序列是 strp[0~2]的所有位的排列组合&#xff0c;strNew {“abc”, “acb”, “bac”, “bca”,”cba”,”cab”} 思路1&#xff1a;枚…

外卖小哥必备!高性价比千元机,送餐更高效

有一群赶时间的人&#xff0c;经常看到他们慌忙的穿梭于大街小巷&#xff0c;他们不仅是城市的风景线&#xff0c;更是无数人心中的温暖使者——外卖小哥 在争分夺秒的背后&#xff0c;一台合适的手机&#xff0c;成为了他们不可或缺的必需品&#xff0c;那什么样的手机更方便呢…

从两眼放光到心碎一地《长相思》第二季搞笑爱情转折

这《长相思》第二季的剧情&#xff0c; 简直是心脏按摩器升级版啊&#xff01; 爷爷一开口&#xff0c;要给玱玹安排馨悦当王后 我这小心脏差点就跟着‘嘭’一声 "哎呀&#xff0c;以为要上演宫廷版《速度与激情》 结果小夭女神一出手&#xff0c; 不是醋坛子翻&#…

Ubuntu 20版本安装Redis教程,以及登陆

第一步 切换到root用户&#xff0c;使用su命令&#xff0c;进行切换。 输入&#xff1a; su - 第二步 使用apt命令来搜索redis的软件包&#xff0c;输入命令&#xff1a;apt search redis 第三步 选择需要的redis版本进行安装&#xff0c;本次选择默认版本&#xff0c;redis5.…

Redis基础教程(十九):Redis分区

&#x1f49d;&#x1f49d;&#x1f49d;首先&#xff0c;欢迎各位来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里不仅可以有所收获&#xff0c;同时也能感受到一份轻松欢乐的氛围&#xff0c;祝你生活愉快&#xff01; &#x1f49d;&#x1f49…

79 单词搜索

题目 给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 单词必须按照字母顺序&#xff0c;通过相邻的单元格内的字母构成&#xff0c;其中“相邻”单元格是那些水平相邻或…

视频短信群发平台的显著优势

视频短信&#xff0c;这一融合了视频、音频与文本的创新通信方式&#xff0c;不仅革新了传统短信的单一形式&#xff0c;更以其独特的魅力引领着移动通信的新风尚。它以移动视频格式&#xff08;如3GP、MP4&#xff09;为载体&#xff0c;通过GPRS网络和WAP无线应用协议&#x…

操作系统之进程控制

进程 一、进程创建1、进程2、fork函数&#xff08;1&#xff09;概念&#xff08;2&#xff09;创建进程执行到内核中的fork代码时&#xff0c;内核做的操作&#xff08;3&#xff09;返回值 3、常规用法4、代码5、执行结果 二、进程终止1、进程的退出结果2、常见退出方法&…

Transformer中的编码器和解码器结构有什么不同?

Transformer背后的核心概念&#xff1a;注意力机制&#xff1b;编码器-解码器结构&#xff1b;多头注意力等&#xff1b; 例如&#xff1a;The cat sat on the mat&#xff1b; 1、嵌入&#xff1a; 首先&#xff0c;模型将输入序列中的每个单词嵌入到一个高维向量中表示&…

JavaScript包管理器:yarn的安装与配置详解

Yarn是一个流行的JavaScript包管理器&#xff0c;它允许开发者使用代码来安装、更新和删除项目中的依赖包。Yarn的安装与配置过程相对简单&#xff0c;以下将详细说明这一过程&#xff1a; 一、Yarn的安装 Yarn的安装可以通过多种方式进行&#xff0c;主要取决于你的操作系统…

深入剖析C++的 “属性“(Attribute specifier sequence)

引言 在阅读开源项目源代码是&#xff0c;发现了一个有趣且特殊的C特性&#xff1a;属性。 属性&#xff08;attribute specifier sequences&#xff09;是在C11标准引入的。在C11之前&#xff0c;编译器特有的扩展被广泛用来提供额外的代码信息。例如&#xff0c;GNU编译器&…

3年经验的B端产品经理,应该是什么水平?

问你一个问题&#xff1a;你觉得3年经验的B端产品经理&#xff0c;应该是什么水平&#xff1f;很多朋友可能也没有仔细想过&#xff0c;自己3年后应该达到一个什么水平&#xff1f;能做什么体量的业务&#xff1f;要能拿多少薪资&#xff1f; 前几天和一个B端产品经理聊天&…

LangChain教程:构建基于GPT的应用程序

ChatGPT和GPT-4的成功表明&#xff0c;通过使用强化学习训练的大型语言模型&#xff0c;可以构建可扩展且功能强大的自然语言处理应用程序。 然而&#xff0c;响应的有用性取决于提示信息&#xff0c;这导致用户探索了提示工程领域。此外&#xff0c;大多数现实世界的自然语言…

突破AI性能瓶颈 揭秘LLaMA-MoE模型的高效分配策略

获取本文论文原文PDF&#xff0c;请在公众号【AI论文解读】留言&#xff1a;论文解读 本文介绍了一种名为“LLaMA-MoE”的方法&#xff0c;通过将现有的大型语言模型&#xff08;LLMs&#xff09;转化为混合专家网络&#xff08;MoE&#xff09;&#xff0c;从而解决了训练MoE…

3DMAX卡死也要安装的10大插件

在探索3DMAX的无限创意边界时&#xff0c;有些插件如同星辰般璀璨&#xff0c;即便面对插件偶尔的“倔强”卡顿&#xff0c;设计师们依然对其爱不释手&#xff0c;誓要将其纳入麾下。以下便是那份令人心动的“卡死也要安装”的10大插件清单&#xff0c;每个都蕴含着设计师对美的…