C++《list》

在本篇当中我们将学习STL中的list,在此list就是我们之前在数据结构学习过的链表,在本篇中我们要来了解list当中的成员函数该如何使用,由于list各个函数的接口和之前学习过的vector类型,因此在学习list的使用就较为轻松。在lis篇章中我们要重点了解的是在下一个篇章当中的list模拟实现中的迭代器实现,由于list底层的物理空间不一定是连续的,因此list迭代器的实现相比之前学习过的容器就复杂多了,在下一篇中将带来细致的讲解。在此之前我们先来了解list该如何使用吧!!


1.构造函数

queue - C++ Reference

通过以上的文档所示就可以看出list类提供的构造函数接口和之前我们学习过的vector非常的相识,都实现了迭代器区间构造;n个指定元素的构造;使用initializer_list实现构造;拷贝构造

例如以下实现:

#include<iostream>
#include<list>
#include<string>
using namespace std;int main()
{string a("abcdef");list<int> lt1;list<int> lt2({ 1,2,3,4,5 });list<int> lt3(a.begin(), a.end());list<int> lt4(10, 9);list<int> lt5(lt2);return 0;
}

2.析构函数

queue - C++ Reference

在list类当中也实现了析构函数,在此该函数不需要我们在使用list时显示调用,这是由于析构函数编译器会在list对象销毁时自动调用

3.赋值运算符重载

list::operator= - C++ Reference

在list实现了赋值运算符重载的函数,这就使得将一个已经初始化的list对象赋值给另一个已经初始化的list对象

例如以下示例:

#include<iostream>
#include<list>
using namespace std;int main()
{list<int> lt1;list<int> lt2({ 1,2,3,4,5 });lt1 = lt2;return 0;
}

4. 容量操作

在list当中由于和之前学习的string、vector不同在存储数据时,每存储一个指定的元素就申请相应的对应合适的内存空间,因此在list就不会提前将空间开好,这就使得list当中容量操作相关的函数只有以下所示:

4.1 size

list::size - C++ Reference

在list提供了用于得到list对象内有效元素个数的成员函数size,到了这里你就可以了解到为什么之前在之前string当中得到有效元素建议使用size而不是length,这就使因为size在其他STL当中也是有提供的,而length只是string特有的,都使用size就利于记忆

4.2 empty

list::empty - C++ Reference

在list也提供用于判断list对象内有效元素是否为空的函数empty,当为空时就返回true,否则就为flase

5. 迭代器

在list类当中由于底层存储数据的内存空间不像string和vector一样物理结构是连续的,因此在list就没有提供下标+[ ]的方式实现对list对象内元素的访问,因此在list就只能使用迭代器来实现

在此list内的迭代器和之前学习过的容器一样也提供了普通迭代器和反向迭代器,并且在这些当中都实现了const和非const版本 

5.1 begin与end

list::begin - C++ Reference

在此list内提供的begin函数还是指向对象的第一个元素,返回值为迭代器

list::end - C++ Reference

在此list内提供的end函数还是指向对象的最后一个元素后一个位置,返回值为迭代器

有了begin()和end()就可以实现对list对象遍历,例如以下示例:

#include<iostream>
#include<list>
using namespace std;int main()
{list<int> lt2({ 1,2,3,4,5 });lt1 = lt2;list<int>::iterator t1 = lt1.begin();while (t1 != lt1.end()){(*t1)++;t1++;}t1 = lt1.begin();while (t1 != lt1.end()){cout << *t1 << " ";t1++;}cout << endl;return 0;
}

6.范围for

在此在list由于实现了迭代器那么就可以使用范围for来对list对象遍历其的元素

例如以下示例:

#include<iostream>
#include<list>
using namespace std;int main()
{list<int> lt1;lt1 = lt2;for (auto x : lt1){cout << x << " ";}cout << endl;return 0;
}

7.取头尾元素

list::front - C++ Reference

list::back - C++ Reference

在list提供了front函数和back函数来分别实现得到list对象内的首元素与尾元素 

例如以下示例:

#include<iostream>
#include<list>
using namespace std;int main()
{list<int> lt2({ 1,2,3,4,5 });cout << "lt2front:" << lt2.front()<<endl;cout << "lt2back:" << lt2.back() << endl;return 0;
}

8.元素修改操作

在list当中提供了以上所示的各种用于修改list对象内元素的函数

8.1 push_front与pop_front

list::push_front - C++ Reference


list::pop_front - C++ Reference

 在list内实现了push_front和pop_front来放分别实现在对象内头插和头删元素
在此要了解到为什么在list会提供该函数而之前学习的string与vector都未实现该函数,这是由于在在链表当中头插和头删元素不需要像顺序表一样在头插和头删时将大量的元素移动,这样就不会出现效率低下的问题

8.2 push_back与pop_back

list::push_back - C++ Reference

 list::pop_back - C++ Reference

 在list内实现了push_back和pop_back来放分别实现在对象内尾插和尾删元素

8.3 insert和erase

list::insert - C++ Reference

list::erase - C++ Reference

在list也提供了inert和erase来实现任意位置的插入和删除,在此实现的接口和vector相识参数都是迭代器或者迭代器区间 

8.4 emplace_front与emplace_back

 list::emplace_front - C++ Reference

list::emplace_back - C++ Reference

在C++11之后实现了以上的两个函数emplace_front和emplace_back,那么这两个函数有什么作用呢?

在此你可以认为emplace_front和emplace_back与push_front和push_back的功能是类似的,功能分别是在list对象头插和尾插指定的数据,但其实这两个函数与push_front和push_back还是有差异的,接下来就来大体的讲解

注:在此emplace_front和emplace_back函数的参数涉及到可变模板参数、右值引用等概念在此不进行讲解,这些要到之后C++11篇章才进行

通过之前的学习我们知道push_front和push_back是可以实现在相应的类对象内插入内置类型的数据,也可以插入自定义类型的数据;并且在此支持隐式类型转换

例如以下示例:

#include<iostream>
#include<list>
using namespace std;class Postion
{
public:Postion(int row,int col):_row(row),_col(col){}private:int _row;int _col;
};int main()
{list<Postion> lt1;Postion p1(1,2);lt1.push_back(p1);//使用匿名对象lt1.push_back(Postion(1, 2));//使用多参数隐式类型转换lt1.push_back({ 1, 2 });return 0;
}

那么以上使用emplace_back不同的参数也可以使用吗

#include<iostream>
#include<list>
using namespace std;class Postion
{
public:Postion(int row,int col):_row(row),_col(col){}private:int _row;int _col;
};int main()
{list<Postion> lt1;Postion p1(1, 2);lt1.emplace_back(p1);lt1.emplace_back(Postion(1, 2));lt1emplace_back({ 1, 2 });return 0;
}

以上代码在VS下就会出现以下的编译报错,这是为什么呢?


 

要解决以上的问题就先了解到emplace_back的形参的类型是根据实参的类型来推导的,那么在以上使用隐式类型转换形参就无法根据实参{ 1, 2 }来推导具体的类型,这里具体的原因就是形参是模板

在此emplace_back和emplace_front最大的特点是支持直接将构造对象的参数直接传emplace_back和emplace_front函数的参数

因此以上代码正确的使用方法是如下所示:

#include<iostream>
#include<list>
using namespace std;class Postion
{
public:Postion(int row,int col):_row(row),_col(col){}
private:int _row;int _col;
};int main()
{list<Postion> lt1;Postion p1(1,2);lt1.push_back(p1);lt1.push_back(Postion(1, 2));lt1.push_back({ 1, 2 });list<Postion> lt1;Postion p1(1, 2);lt1.emplace_back(p1);lt1.emplace_back(Postion(1, 2));//lt.1emplace_back({ 1, 2 });lt1.emplace_back( 1, 2 );return 0;
}

注:在此由于emplace_back是直接构造去初始化节点,而push_back需要通过构造外加拷贝实现的,因此emplace_back相比push_back效率更高

9. list内特有的操作

在list中提供了以上特有的函数来实现逆置、排序等的操作,这些操作是之前我们在string和vector当中没有提供的,那么接下来我们就来了解这些函数的作用以及使用方法,但张这些函数其实在实践当中的使用频率非常少,因此我们只需要了解基本的使用方法即可

9.1 splice

list::splice - C++ Reference

在此splice的作用是将一个list对象的值转移给另一个list的对象,并且转移之后被转移对象会变为空

例如以下示例:

#include<iostream>
#include<list>
using namespace std;int main()
{list<int> mylist1, mylist2;list<int>::iterator it;// set some initial values:for (int i = 1; i <= 4; ++i)mylist1.push_back(i);      // mylist1: 1 2 3 4for (int i = 1; i <= 3; ++i)mylist2.push_back(i * 10);   // mylist2: 10 20 30it = mylist1.begin();++it;                         // points to 2mylist1.splice(it, mylist2); // mylist1: 1 10 20 30 2 3 4// mylist2 (empty)// "it" still points to 2 (the 5th element)return 0;
}

再来看以下示例:

有一种LRU算法,即最近最少使用算法

在此有一个数组要将使用到的元素位置移到数组的头部,那么该如何实现呢?

在此就可以使用到splice函数来实现

#include<iostream>
#include<list>
using namespace std;int main()
{list<int> a = { 1,2,3,4,5,6,7,8,9 };int x;while (cin >> x){auto found = find(a.begin(), a.end(), x);if (found != a.end()){a.splice(a.begin(), a, found);}for (auto x : a){cout << x << " ";}cout << '\n';}return 0;
}

9.2 remove

list::remove - C++ Reference

在此erase的作用是将list内的值为指定值的元素删除,可以认为remove是find和erase的结合体,在之前使用erase删除指定值的元素时要先使用find查找到相应迭代器的位置,再将相应的迭代器传给erase才能实现,而remove就可以直接实现以上的操作

例如以下示例:

#include<iostream>
#include<list>
using namespace std;int main()
{int myints[] = { 17,89,7,14 };list<int> mylist(myints, myints + 4);mylist.remove(89);cout << "mylist contains:";for (auto x : mylist){cout << x << " ";}cout << '\n';return 0;
}

注:在此的remove_if涉及到仿函数,在此先不做讲解,到之后stack和queue再介绍仿函数是什么

9.3  merge

find - C++ Reference

在此在list内提供了merge来实现两个链表的归并,在此要求是两个链表是有序的才能进行归并,并且将一个list对象归并到另一个对象之后,这个list对象就为空了

例如以下示例:

#include<iostream>
#include<list>
using namespace std;int main()
{list<int> lt1({1,3,5,7,9});list<int> lt2;lt2.push_back(2);lt2.push_back(4);lt2.push_back(6);lt2.push_back(8);lt1.merge(lt2);//(lt2 is now empty)for (auto x : lt2){cout << x << " ";}cout << '\n';for (auto x : lt1){cout << x << " ";}cout << '\n';return 0;
}

9.4 unique

list::unique - C++ Reference

在此list提供了unique来实现去重,将list对象内重复的元素只保留一个其他重复的去除掉,在此前提list内的数据是有序的才能去去重

例如以下示例:

#include<iostream>
#include<list>
using namespace std;int main()
{list<int> lt1({ 1,2,3,3,3,5,7,8,9 });lt1.unique();for (auto x : lt1){cout << x << " ";}cout << '\n';return 0;
}

9.5 sort

list::sort - C++ Reference

在list还提供了对对象内元素进行排序的函数sort,在此sort默认排的是升序

例如以下示例:

#include<iostream>
#include<list>
using namespace std;int main()
{list<int> lt1;lt1.push_back(9);lt1.push_back(-2);lt1.push_back(3);lt1.push_back(-10);for (auto x : lt1){cout << x << " ";}cout << '\n';lt1.sort();for (auto x : lt1){cout << x << " ";}cout << '\n';return 0;
}

以上sort默认能实现升序是因为形象的缺省值默认是less,在此less是一个仿函数, 在此我们只要先了解到仿函数是一个类就可以了,能实现比较是由于在类内部实现了()的运算符重载,在之后的stack与queue章节将会详细讲解

在此使用sort时要实现降序就要使用另外的一个仿函数greater

例如以上示例要排成降序:

#include<iostream>
#include<list>
using namespace std;int main()
{list<int> lt1;lt1.push_back(9);lt1.push_back(-2);lt1.push_back(3);lt1.push_back(-10);for (auto x : lt1){cout << x << " ";}cout << '\n';//使用匿名对象创建一个greater类型的对象作为sort的实参lt1.sort(greater<int>());for (auto x : lt1){cout << x << " ";}cout << '\n';return 0;
}

在此你可以会有一个疑惑,之前在vector当中要进行排序调用算法库内的sort就可以实现了,那么为什么在list内要单独实现一个sort,不是直接调用算法库内的就好了吗?

在此我们要了解的是之前是按照使用修改的角度将迭代器分为普通迭代器、const迭代器、反向迭代器、const反向迭代器,其实迭代器还可以从功能的角度分为单向迭代器、双向迭代器、随机迭代器

在此单向迭代器的特点是只支持++双向迭代器的特点是只支持++和--随机迭代器的特点是支持++、--还有+和-。经典的单向迭代器有一个叫做forward_list的容器,经典的双向迭代器有list,经典的随机迭代器有之前我们学习过的string、vector

在此提供算法库内的sort文档就可以看出该sort要传随机迭代器,这是由于算法库内的sort的底层是快速排序,这就需要支持随机访问,因此由于list不是随机迭代器因此就无法使用算法库内的sort

在此我们还要了解到的是以上的三种迭代器其实是继承的关系,由于我们还没有学习到C++中的继承也可以认为三种迭代器是以下所示的集合关系

那么在了解了以上的知识之后接下来看看list内的sort相比算法库内的sort效率如何呢?

在此我们通过以下两段代码来测试

先来看以下这段代码

#include<iostream>
#include<list>
#include<vector>
#include<algorithm>
using namespace std;void test_op1()
{srand(time(0));const int N = 1000000;list<int> lt1;list<int> lt2;vector<int> v;for (int i = 0; i < N; ++i){auto e = rand() + i;lt1.push_back(e);v.push_back(e);}int begin1 = clock();// 排序sort(v.begin(), v.end());int end1 = clock();int begin2 = clock();lt1.sort();int end2 = clock();printf("vector sort:%d\n", end1 - begin1);printf("list sort:%d\n", end2 - begin2);
}int main()
{test_op1();return 0;
}

以上代码输出结果如下所示:
在以上代码当中我们使用rand生成100万的整型数据分别存储在vector对象和list对象内,之后vector对象调用算法库内的sort进行排序,list使用其内部的成员函数sort进行排序,之后通过输出的结果就可以看出这两个sort的效率有什么差别


 通过输出结果就可以看出算法库内的sort要快不少

再来看以下代码:

#include<iostream>
#include<list>
#include<vector>
#include<algorithm>
using namespace std;void test_op2()
{srand(time(0));const int N = 1000000;list<int> lt1;list<int> lt2;for (int i = 0; i < N; ++i){auto e = rand();lt1.push_back(e);lt2.push_back(e);}int begin1 = clock();// 拷贝vectorvector<int> v(lt2.begin(), lt2.end());// 排序sort(v.begin(), v.end());// 拷贝回lt2lt2.assign(v.begin(), v.end());int end1 = clock();int begin2 = clock();lt1.sort();int end2 = clock();printf("list copy vector sort copy list sort:%d\n", end1 - begin1);printf("list sort:%d\n", end2 - begin2);
}int main()
{test_op2();return 0;
}

你可能觉得第一段代码的结果还不够直观,那么就再来看以上的第二段代码,以上代码先比第一段代码的区别是一开始生成的100万个随机数是先存放在list对象内之后再拷贝给vector对象,再调用算法库内的sort进行排序。那么这种情况下是不是直接使用list内的sort效率会比拷贝再使用算法库内的sort效率要高呢?

接下来来看以上代码的输出结果:

通过以上的输出结果就可以看出先拷贝再使用算法库内的sort都比直接使用list内的sort效率要高,这就可以说明算法库内的sort是要比list内的sort要高效不少的。因此再之后要使用到大量数据的排序时最好使用vector

9.6 reverse

list::reverse - C++ Reference

 在list还提供了逆置list对象元素函数reverse

例如以下示例:

#include<iostream>
#include<list>
using namespace std;int main()
{list<int> lt1;lt1.push_back(9);lt1.push_back(-2);lt1.push_back(3);lt1.push_back(-10);for (auto x : lt1){cout << x << " ";}cout << '\n';//lt1.sort(greater<int>());lt1.reverse();for (auto x : lt1){cout << x << " ";}cout << '\n';return 0;
}

以上就是本篇的全部内容了,接下来在下一篇当中将带来list的模拟实现,在模拟实现中我们将感受到list内的迭代器和之前学习的容器的具体不同,未完待续…… 

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

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

相关文章

爬虫-------字体反爬

目录 一、了解什么是字体加密 二. 定位字体位置 三. python处理字体 1. 工具库 2. 字体读取 3. 处理字体 案例1:起点 案例2:字符偏移: 5请求数据 - 发现偏移量 5.4 多套字体替换 套用模板 版本1 版本2 四.项目实战 1. 采集目标 2. 逆向结果 一、了解什么是…

Go-性能优化、优化分析、调优实战pprof

使用官方自带benchmark进行基准性能测试 第一个是函数名-核数 第二个是执行次数 第三个是一次执行时间 第四个是一次执行的多大的内存 第五个是一次执行申请几次内存 slice用的时候在make&#xff08;&#xff09;初始化切片时提供容量信息 data:make([]int,0) data:make([]in…

Node.js——fs模块-文件追加写入

1、appendFile/appendFileSync 追加写入 appendFile 作用是在文件尾部追加内容&#xff0c;appendFile 语法与 writeFile 语法完全相同 语法&#xff1a; 返回值&#xff1a;二者都为&#xff1a; undefined 本文的分享到此结束&#xff0c;欢迎大家评论区一同讨论学习&#…

单元测试日志打印相关接口及类 Logger

LoggerFactory 简介 单元测试常用日志打印工具LoggerFactory。 LoggerFactory 代码结构 LoggerFactory 是 JUnit 平台中的一个类&#xff0c;用于创建 Logger 实例。它被设计用于提供日志记录功能&#xff0c;使得 JUnit 在执行测试时能够记录信息、警告、错误等。 LoggerFact…

《Linux运维总结:基于银河麒麟V10+ARM64架构CPU部署redis 6.2.14 TLS/SSL哨兵集群》

总结:整理不易,如果对你有帮助,可否点赞关注一下? 更多详细内容请参考:《Linux运维篇:Linux系统运维指南》 一、简介 Redis 哨兵模式是一种高可用性解决方案,它通过监控 Redis 主从架构,自动执行故障转移,从而确保服务的连续性。哨兵模式的核心组件包括哨兵(Sentine…

ENSP作业——园区网

题目 根据上图&#xff0c;可得需求为&#xff1a; 1.配置交换机上的VLAN及IP地址。 2.设置SW1为VLAN 2/3的主根桥&#xff0c;设置SW2为VLAN 20/30的主根桥&#xff0c;且两台交换机互为主备。 3.可以使用super vlan。 4.上层通过静态路由协议完成数据通信过程。 5.AR1作为企…

Navicat16 安装图文配置

Navicat是什么&#xff1f; Navicat 是一个数据库管理工具&#xff0c;它提供了一个图形界面来方便地管理和操作各种数据库。Navicat 支持多种数据库类型&#xff0c;包括 MySQL、MariaDB、SQL Server、SQLite、PostgreSQL 和 MongoDB&#xff0c;并且也支持通过 SQL 命令直接连…

模块化开发 webpack

模块化开发 & webpack 1、模块化开发 & webpack1.1 webpack 执行过程1.1.1 初始化1.1.2 编译1.1.3 输出 2.1 webpack 基础配置2.1.1 Entry2.1.1.1 context2.1.1.2 Entry类型 2.1.2 output2.1.2.1 filename2.1.2.2 publicPath2.1.2.3 path2.1.2.4 libraryTarget 和 libr…

OpenEuler 使用ffmpeg x11grab捕获屏幕流,rtsp推流,并用vlc播放

环境准备 安装x11grab(用于捕获屏幕流)和libx264(用于编码) # 基础开发环境&x11grab sudo dnf install -y \autoconf \automake \bzip2 \bzip2-devel \cmake \freetype-devel \gcc \gcc-c \git \libtool \make \mercurial \pkgconfig \zlib-devel \libX11-devel \libXext…

uni-app 图标库整合最佳实践:使用 iconfont 构建属于自己的图标库

一. 前言 在前端开发中&#xff0c;图标已经成为页面设计中不可或缺的一部分。图标可以使界面更加美观、清晰&#xff0c;并且能够提升用户体验。而使用图标库来管理和引用图标资源&#xff0c;可以带来更多的便利和效率。 而在众多的图标库中&#xff0c;iconfont 独树一帜。…

刷题强训 (day1) -- 数字统计

1、数字统计 1.1题目 1.2 思路 根据题目得知我们要统计2出现的次数&#xff0c;那么这就是一个枚举 数字拆分的过程&#xff0c;先设一个变量count统计2出现的次数&#xff0c;那么count怎么变化呢&#xff1f; 当然了出现一个2&#xff0c;count就1&#xff0c;重点在于如何…

AI-基本概念-向量、矩阵、张量

1 需求 需求&#xff1a;Tensor、NumPy 区别 需求&#xff1a;向量、矩阵、张量 区别 2 接口 3 示例 4 参考资料 【PyTorch】PyTorch基础知识——张量_pytorch张量-CSDN博客

Halcon区域分割之分水岭分割法

现实中我们见到过有山有湖的景象&#xff0c;那么一定是水绕山、山围水的情形。当然可在需要的时候人工构筑分水岭&#xff0c;以防集水盆之间的互相穿透。而区分高山与水的界线以及湖与湖之间的间隔&#xff0c;就是分水岭。 分水岭分割法是一种基于拓扑理论的数学形态…

数据结构与算法——图

图 1.图的定义和表示 图的定义 图G由集合V和集合E组成&#xff0c;记作G(V,E),其中&#xff1a; 1、V是顶点元素的有限集合&#xff1b; 2、E是顶点间关系——边的有限集合。 3、边是顶点的无序对或有序对。 无向图和有向图&#xff1a; 无向图 由没有方向的边构成的图…

FebHost:法国.FR域名的市场前景和挑战

.FR域名的未来前景如何&#xff1f; .fr域名在2023年经历了显著增长&#xff0c;新注册量大幅增加。这一积极趋势凸显了法国 VSE&#xff08;极小型企业&#xff09;和 SME&#xff08;中小型企业&#xff09;数字化转型的持久影响&#xff0c;这一转变早在 2022 年就已开始。…

SQL进阶技巧:如何计算复合增长率?

目录 0 场景描述 1 数据准备 2 问题分析 3 小结 0 场景描述 复合增长率是第N期的数据除以第一期的基准数据&#xff0c;然后开N-1次方再减去1得到的结果。假如2018年的产品销售额为10000&#xff0c;2019年的产品销售额为12500&#xff0c;2020年的产品销售额为15000&…

开源的 API 学习平台「GitHub 热点速览」

前有 5 万颗星标的开源项目 HTTPie 因误操作导致 Star 清零&#xff08;2022 年&#xff09;&#xff0c;上周知名开源项目 Elasticsearch 也经历了 Star 一夜清零的事件。这些事故的原因均是管理员误将开源项目从公开状态转为私有状态所导致。为避免类似事件再次发生&#xff…

华为HD集群重启NAMENODE实例操作步骤

华为HD集群重启NAMENODE实例操作步骤 管理员账号进入FI——服务——HDFS&#xff0c;选择角色&#xff1a;namenode重启namenode&#xff08;备&#xff09; 如下图&#xff1a;点击【实例】–角色选择【Namenode】–选择备节点&#xff08;自己记录一下当前备节点的IP&…

LoRA:大型语言模型(LLMs)的低秩适应;低秩调整、矩阵的低秩与高秩

目录 LoRA:大型语言模型(LLMs)的低秩适应 一、LoRA的基本原理 二、LoRA的举例说明 三、LoRA的优势 低秩调整、矩阵的低秩与高秩 一、低秩调整(LoRA) 二、矩阵的低秩 三、矩阵的高秩 LoRA:大型语言模型(LLMs)的低秩适应 LoRA(Low-Rank Adaptation of LLMs),…

CST参数扫描设置细节

cst参数扫描的细节 点开参数扫描对话框&#xff0c;新建扫描参数&#xff0c; 例如参数a进行扫描1-2&#xff0c;0.5的步长&#xff0c;这样最后会出现3个参数的仿真结果。 这时如果增加参数b的扫描&#xff0c;在同一sequence下&#xff0c;同样1-2&#xff0c;0.5的步长&…