STL入门教程二:list的使用

      上次给大家介绍了vector的用法,这次我为大家介绍另一个用途广泛的容器,那就是list。我们首先来比较一下两种容器的异同。vector和list在结构上都表现为数组,只不过vector是一个其中的元素都在一块内存中连续分布的数组,类似于C/C++在栈上定义一个数组的内存布局;而list中元素在内存中的布局不是连续的,其类似于C/C++在堆上定义一个数组的内存布局。由于在内存布局上的差异,使这两种容器要根据不同的场合来选择使用。

      如需要快速访问容器中元素的场合,我们应该使用vector,由于vector中的元素是连续存储的,所以我们能够直接的访问第n个元素;而使用list的话,如果我们要访问第n个元素,由于元素不是在内存中连续存储的,下一个元素的内存地址保存在前一个元素中,所以我们必须一个一个的访问前面的元素,最后才能访问第n个元素。

      如系统中没有很多连续空间的场合,我们应该使用list。因为如果没有我们所需要的连续内存空间的话,vector在构造或者插入新的元素的时候会失败而抛出bad_alloc异常。而由于list不需要连续的内存空间,所以只要系统中还有可分配的空间,都可以插入新的元素。

      如需要快速的在容器中大量的插入和删除元素的话,我们应该使用list。比如在vector中插入/删除一个元素的话,我们需要移动插入/删除位置之后的所有元素。如果在vector插入/删除元素后有大量元素的情况下,这些移动和删除操作会大量的消耗CPU时间。而在使用list进行这些操作的时候,其仅仅是修改插入/删除元素之前的元素到后一个元素的指针则可以完成这些操作。这样可以节约大量的CPU时间。

      学习完了这些概念后,下面让我们再来看看list中一些具体的操作。

      构造函数:

      explicit list (const Allocator& = Allocator());       默认构造函数,构造一个空的list,使用代码为               explicit list (size_type n, const T& value= T(), const Allocator& = Allocator());       重复序列构造函数,构造一个包含n个值为value的list,使用代码为                 template <class InputIterator> list (InputIterator first, InputIterator last, const Allocator& = Allocator());        迭代器构造函数,构造一个包含[first, last)范围内元素的list,使用代码为          

       

       list (const list<T,Allocator>& x);        复制构造函数,构造一个包含x所有元素的list,使用代码为       

 

       list<T,Allocator>& operator= (const list<T,Allocator>& x);

       删除掉原容器中所有的元素,然后将x中的元素拷贝到原容器中,使用代码为

      

 

       iterator begin ();
       const_iterator begin () const;

       获取指向list中首元素的迭代器,其使用方法跟vector相同,使用代码见STL入门教程一:vector的使用

 

       iterator end ();
       const_iterator end () const;

       获取指向list中末尾元素的迭代器,其使用方法跟vector相同,使用代码见STL入门教程一:vector的使用

 

       reverse_iterator rbegin();
       const_reverse_iterator rbegin() const;

       获取指向list中末尾元素的反向迭代器,其使用方法跟vector相同,使用代码见STL入门教程一:vector的使用

 

       reverse_iterator rend();
       const_reverse_iterator rend() const;

       获取指向list中首元素的反向迭代器,其使用方法跟vector相同,使用代码见STL入门教程一:vector的使用

 

       size_type max_size()

       获取一个list在当前的编译器和系统下所能包含的最大元素,在VS2008和WIN7下,这个值为1073741823

 

       void resize (size_type sz, T c = T());

       重新分配容器的大小到sz。详细说明见STL入门教程一:vector的使用

 

       void push_back (const T& x);

       插入元素x到list的末尾,使用代码见STL入门教程一:vector的使用

 

       iterator insert (iterator position, const T& x);

       在迭代器position处插入值为x的元素,返回新位置的迭代器


       void insert (iterator position, size_type n, const T& x);

       在迭代器position处插入n个值为x的元素


       template <class InputIterator>
       void insert ( iterator position, InputIterator first, InputIterator last );

       在迭代器position处插入迭代器first(包含)和last(不包含)之间的元素

      

       以上的插入操作和vector的使用方法和效果是一样的,只是有一点不同的是。先前从该list获取的迭代器在插入操作后仍然有效。使用代码见STL入门教程一:vector的使用

 

       iterator erase ( iterator position )

       删除迭代器postion处的元素,返回删除元素的后一个元素的迭代器

 

       iterator erase ( iterator first, iterator last )

       删除迭代器first(包含)到last(不包含)之间的元素,返回最后一个删除元素的后一个元素

 

       以上的删除操作和vector的使用方法和效果是一样的,只是有一点不同的是。先前从该list获取的迭代器在插入操作后仍然有效。使用代码见STL入门教程一:vector的使用

 

       下面就轮到这边文章的重头戏了,让我们来看看list所拥有的独有的方法

 

       void splice (iterator position, list<T,Allocator>& x);
       void splice (iterator position, list<T,Allocator>& x, iterator i);
       void splice (iterator position, list<T,Allocator>& x, iterator first, iterator last);

       感觉这个函数取的名字和它的用途有点不符合,不知道第一次看到这个函数,并且用过C#语言String类的朋友会不会认为:这个函数的作用是用来切割list各个部分内容的。反正我第一次看到这个函数的名字是这样认为的囧。其实这个几个函数的用途就是用来移动一个list中的元素到另一个list中的。大家是不是认为叫作move更好呢。

       参数position表示要移动的目标list(也就是调用这个操作的list)的迭代器,x表示要移动的原list,first和last表示x的迭代器。使用代码如下:

      

 

       void remove (const T& value)

       删除list中所有值为value的元素。使用代码如下:

      

 

       template <class Predicate>
       void remove_if (Predicate pred)

       根据操作pred,删除list中相应的元素。pred的函数原型为bool pred(const T& value),其中类型T为list元素的类型,value为list中每个元素的值,当传入改制时函数返回为true时则删除相应的节点。

      

 

       void unique ( );
       template <class BinaryPredicate>
       void unique (BinaryPredicate binary_pred);

       第一个版本list中连续一组相同元素唯一,比如list中有元素1, 1, 2, 1,则调用unique操作后list中的元素变为1, 2, 1。由于unique操作只能使一组连续的元素在一个list中唯一,所以在调用unique之前应该调用sort操作,才能使一个list中的所有元素保持唯一。

       第二个版本则根据操作binary_pred所定义的规则来使list中符合规则的一组连续元素保持唯一。binary_pred的函数定义为bool unique_pred(T prev, T next),其中prev表示要比较的两个相邻元素之中在list中靠前的元素,next表示靠后的元素。当返回为true时,则删除next元素。使用代码如下:

      

 

       void merge (list<T,Allocator>& x);
       template <class Compare>
       void merge (list<T,Allocator>& x, Compare comp);

       合并已排序的源list到已排序的目标list中。merge操作和splice操作比较相似,都是将源list中的元素移动到目标list,不过和splice简单的将元素移动到目标list末尾不同的是,merge会把源list中的元素按照一定的规则合并到目标list中。在第一个版本的函数中,这个规则是按照类型T从小到大排列的。

       第二个版本的函数的规则由comp函数决定,该函数的原型为bool comp(T next, T prev)

       使用代码如下:

       

 

       好了,list的介绍就到这里,下次让我们来看看map。

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值