前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【STL】list的使用

【STL】list的使用

作者头像
诺诺的包包
发布2023-10-15 13:58:34
1600
发布2023-10-15 13:58:34
举报
文章被收录于专栏:个人笔记总结个人笔记总结

 放在专栏【C++知识总结】,会持续更新,期待支持🌹

1、list简介

  • list是可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代。
  • list的底层是带头双向链表结构,双向链表中每个元素存储在互不相关的独立节点中,在节点中通过指针指向 其前一个元素和后一个元素。
  • 与其他的序列式容器相比(array,vector,deque),list通常在任意位置进行插入、移除元素的执行效率更好(时间复杂度:O(1))。
  • 与其他序列式容器相比,list和forward_list(单向链表)最大的缺陷是不支持任意位置的随机访问,比如:要访问list 的第6个元素,必须从已知的位置(比如头部或者尾部)迭代到该位置,在这段位置上迭代需要线性的时间 开销;list还需要一些额外的空间,以保存每个节点的相关联信息。

相对于vector来说,list对于空间的运用有着绝对的精准,不会存在一点的浪费,因为list是每插入或删除一个元素,就配置或释放一个元素空间。而vector则采用1.5或者2倍扩容机制,会存在一定程度上的空间浪费。两者各有优点。

2、list的数据结构

list本身与list节点,这两个是完全不同的结构,是需要分开来设计的,对于一个list节点来说,由于list是双向环状链表(双向带头循环链表),所以需要提供两个指针,一个指向前一个元素,一个指向另一个元素,同时还需要一个val,用来存储数据。如下所示为SGI版本的list底层(稍作修改,便于学习):

代码语言:javascript
复制
//list节点
template<class T>
struct _list_node
{
	_list_node<T>* _prev;//指向前一个元素
	_list_node<T>* _next;//指向后一个元素
	T _data;             //用来存储数据
};
//list
template<class T>
class list
{
	typedef _list_node<T> node;
public:
	//.....
private:
	node* _head;//只需要一个指针,便可以表示整个双向循环链表
};

需要注意到的是,list由于存储空间并不是连续的,因此这里的迭代器并不像string与vector那样,是一个原生指针,这里list的迭代器是用一个对象,来模拟指针的行为,从而实现对list元素的访问。具体在后面模拟实现时会详细讲解。这里我们先了解其使用即可:

3、list的使用

在使用前,需要包含头文件<list>

3.1、构造相关

3.1.1、构造一个空容器
代码语言:javascript
复制
	list<int> l;//构造一个存储元素为int类型的空list
3.1.2、构造含有n个val的某类型容器
代码语言:javascript
复制
	list<int> l(10, 5);//构造一个含有10个元素,元素类型为int,值为10的list
3.1.3、拷贝构造
代码语言:javascript
复制
	list<int> l1(5, 1);//l1:1 1 1 1 1
	//拷贝构造
	list<int> l2(l1);  //l2:1 1 1 1 1
	//也可以写成list<int> l2=l1;
3.1.4、迭代器区间构造
代码语言:javascript
复制
	//迭代器区间构造(左闭右开)
	string s("hello world!");
	list<char> l(s.begin(), s.begin() + 5);
	//l:h e l l o

可以看到,整体使用实际上与string或vector并无太大区别,用起来很简单。

3.2、容量相关

3.2.1、size与empty

这里list只存在size,表示list中有效节点个数,而empty就不用说了,用来判断容器是否为空。

3.2.2、resize

与vector相同,resize可以实现对有效元素的扩容或“缩容”,当resize(n,val)时,如果n的值>当前size值,则list会进行扩容到size为n,扩容出来的元素值用val来充当,当n的值<size时,list会缩容到n大小。如下:

3.3、元素访问

3.3.1迭代器

迭代器是个很奇妙的设计,所有的容器,通过迭代器都可以进行访问容器中的元素,list也不例外,用起来也很简单,就像vector中一样用即可。

 这里,begin与end分别指向list中第一个有效元素,以及最后一个有效元素的下一个位置,而我们的begin与end区间,通常都是左闭右开,对于环状的链表来说,只需要在尾端加入一个空白节点,便符合STL规范之“前闭后开”。(实际就是一个双向带头循环链表)如下所示:

 当然,list中也存在const迭代器,以及反向迭代器,分别对应cbegin与cend(const正向迭代器)、rbegin与rend(反向迭代器)、crbegin与crend(const反向迭代器),const类型的迭代器的特点就是不能对指向的元素做修改。不过需要注意的是,rbegin与end对应,rend与begin对应。

 这里我们在后续模拟实现时也会讲到。

list有关迭代器的相关接口

 3.3.2、迭代器失效问题

我们知道迭代器失效指的就是迭代器指向了一块不属于它的空间,或者指向的空间已经被销毁了。这里list由于不像vector那样,vector的插入操作可能会引起扩容,从而导致迭代器失效,而list则不会,因为list的底层结构为带头结点的双向循环链表,因此在list中进行插入时是不会导致list的迭代 器失效的,只有在删除时才会失效,并且失效的只是指向被删除节点的迭代器,其他迭代器不会受到影响

如下所示为迭代器失效场景:

 解决方法也很简单,更新it即可。如下所示:

 3.3.3、front与back

front用于获取list中的第一个元素,back用于获取list中最后一个元素。如下所示:

 3.4、插入删除操作

list相比于vector的优点之一就在于,vector只有在尾部插入删除才是效率最高(O(1)),而list在任意位置插入删除,都可以实现O(1),很高效。接下来将讲解list的插入删除相关接口

3.4.1、push_back与pop_back

这俩函数前者实现尾插,后者实现尾删操作,用起来也很简单,如下所示:

 3.4.2、push_front与pop_front

push_front实现在头部插入元素,pop_front则为在头部删除一个元素,如下:

 3.4.3、insert与erase

insert与erase实现在任意位置插入与删除。

在c++98中,提供了insert的三种插入方式,分别为:在pos位置插入一个元素val;在pos位置插入n个元素,每个元素为val;在pos位置插入一段迭代器区间构成的元素(左闭右开)。

 erase也提供了两种删除方式:删除pos位置的元素;删除区间[first,last)的元素

 3.5、其它操作

list中还提供了一些其它接口,不过有些并不常用,这里只挑选几个进行讲解,可自行翻阅文档查看。《点击跳转

3.5.1、reverse

reverse函数用于实现链表的逆置,如下:

3.5.2、swap

很熟悉了,用于两个链表实现数据交换。

3.5.3、remove

remove(val),用来移除链表中元素为val的节点:

3.5.4、sort

sort用来实现对链表进行排序。默认为升序排序,如下:

3.5.5、unique

该函数用来删除相邻的重复元素,我们可以利用sort+unique实现对链表排序+去重。如下所示:

end.

生活原本沉闷,但跑起来就会有风!🌹

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2023-06-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1、list简介
  • 2、list的数据结构
  • 3、list的使用
    • 3.1、构造相关
      • 3.1.1、构造一个空容器
      • 3.1.2、构造含有n个val的某类型容器
      • 3.1.3、拷贝构造
      • 3.1.4、迭代器区间构造
    • 3.2、容量相关
      • 3.2.1、size与empty
      • 3.2.2、resize
    • 3.3、元素访问
      • 3.3.1迭代器
      •  3.3.2、迭代器失效问题
      •  3.3.3、front与back
    •  3.4、插入删除操作
      • 3.4.1、push_back与pop_back
      •  3.4.2、push_front与pop_front
      •  3.4.3、insert与erase
    •  3.5、其它操作
      • 3.5.1、reverse
      • 3.5.2、swap
      • 3.5.3、remove
      • 3.5.4、sort
      • 3.5.5、unique
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档