std::list使用方法

List

  List使用一个doubly linked list(双向串列)管理元素,按惯例,C++标准库并未明定实现方式,只是遵守list的名称、限制和规格。List其实相当于数据结构中的双链表。
在这里插入图片描述
  使用list时必须先包含头文件

#include<list>

 
 
  • 1

  其中的list类型定义于namespace std 中,是一个class template:

template<
    class T,
    class Allocator = std::allocator<T>
> class list;

 
 
  • 1
  • 2
  • 3
  • 4

  List的元素可以是任何类型T,Allocator用于指定内存模型,默认是C++ 标准库提供的类型。

List 的能力

  List的内部结构与vector和deque完全不同,List对象提供了两个pointer,分别指向前后元素。因此,List在几个方面与vector和deuqe不同:
  1.List不支持随机访问,因此访问元素的效率较低;
  2.任何位置上,执行元素的插入和移除都很快,始终是常量时间内完成,因为无需移动任何元素;
  3.安插和删除的操作不会因此指向其他元素的pointer、reference、iterator失效;
  4.List对异常的控制是,要么操作成功,要么什么都不发生。

List 操作

  List容器提供的一般STL所具备的通用能力,但相比于vector和deque具有如下不同——
  1.由于不支持随机访问,所以List没有at函数和下标操作符;
  2.List并未提供容量、空间重新分配等操作的函数,因为没有必要,每个元素有自己的内存,在元素被删除前一直有效;
  3.List提供不少特殊成员函数,专门用于移动和移除元素,较之同名的STL通用算法,这些函数执行起来更加迅速,因为他们只需要调整几个pointer即可。

构建、复制和销毁(Create、Copy and Destroy)

  List的构建、复制和销毁操作,与每一个序列式容器相同——

序号操作效果
1list<Elem> cDefault构造函数,产生一个list,没有任何元素
2list<Elem>c(c2)
list<Elem>c=c2
Copy构造函数,建立c2同型list并成为c2的一份副本,该复制是深度复制
3list<Elem>c(rv)
list<Elem>c=rv
rv是一个list右值引用,那么这里的构造函数是一个Move构造函数,建立一个新的list,取右值内容(C++11新特性)
4list<Elem>c(n)利用元素的默认构造函数生成一个大小为n(容量也为n)的vector
5list<Elem>c(n,elem)建立一个大小为n的list,并初始化为elem
6list<Elem>c(beg,end)建立一个list,并以迭代器所指向的区间[beg,end)作为元素值
7list<Elem>c(initlist)
list<Elem>c=initlist
建立一个list,以初值列initlist元素为初值(C++11新特性)
8c.~list()销毁所有元素,释放内存

非更易型操作(Nonmodifying Operation)

  List也提供元素比较、查询大小等操作——

序号操作效果
1c.empty()容器为空返回true,不为空返回false,相当于size()==0
2c.size()返回当前元素的个数
3c.max_size()返回元素个数之最大可能量
4c1==c2对每个元素调用c1==c2,全部相等返回true
5c1!=c2只要有一个元素相等,返回true,相当于!(c1==c2)
6c1>c2,c1>=c2,c1<c2,c1<=c2同上,依次类推

元素访问(Element Access)

  与vector和deque不同,list没有at和下标运算符,因此只有两个直接访问元素的函数。或者使用range-based for循环遍历所有元素——

序号操作效果
1c.front()返回第一个元素(不检查是否存在第一个元素)
2c.back()返回最后一个元素(不检查是否存在最后一个元素)
	list<int> l {1,2,3,4,5,6,7,8,9};
	cout<<l.front()<<endl;
	cout<<l.back()<<endl;

 
 
  • 1
  • 2
  • 3

在这里插入图片描述

赋值(Assignment)

  和其他序列式容器一样,list提供了通用的赋值动作+

序号操作效果
1c1=c2把c2的全部元素赋值给c
2c=rv将rvalue 右值引用以 move assignment的方式赋值给c(C++11新特性
3c = initlist将初值列initlist的所有元素赋值给c(C++11新特性)
4c.assign(n,elem)复制n个elem,赋值给c
5c.assign(beg,end)复制迭代器指向区间[beg,end)内容,赋值给c
6c.assign(initlist)将初值列initlist的所有元素赋值给c
7c.swap(c2)置换c和c2的数据
8swap(c1,c2)置换c1和c2的数据

迭代器函数(Iterator Function)

 运用迭代器访问list的唯一方法。由于list不支持随机访问,这些迭代器只是双向迭代器,因此所有用到随机迭代器的算法——特别是排序算法——都不能进行处理list,但好在list提供了sort函数来取而代之。

序号操作效果
1c.begin()返回一个bidirectional iterator指向第一个元素
2c.end()返回一个bidirectional iterator指向的之后一个元素
3c.cbegin()返回一个const bidirectional iterator指向的第一个元素(C++11新特性
4c.cend()返回一个const bidirectional iterator指向的最后一个元素(C++11新特性
5c.rbegin()返回一个反向迭代器(reverse iterator)指向的第一个元素
6c.rend()返回一个reverse iterator指向的最后一个元素
7c.crbegin()返回一个const reverse iterator指向的第一个元素(C++新特性
8c.crend()返回一个const reverse iterator指向的最后一个元素(C++11新特性
	list<int> l {1,2,3,4,5,6,7,8,9};
	for(auto it = l.begin();it!=l.end();it++){
		cout<<*it<<" ";
	}

 
 
  • 1
  • 2
  • 3
  • 4

在这里插入图片描述

插入与移除(Inserting and Removing)

  list除了提供了通用的元素插入移除操作之外,还增加了适用于list的remove和remove_if算法。

序号操作效果
1c.push_back(elem)在list末尾插入元素elem
2c.pop_back()移除最后一个元素,但是不返回该元素
3c.push_front(elem)在首部插入元素elem
4c.pop_front()移除首部元素,但是不返回该元素
5c.insert(pos,elem)在iterator指向的pos位置的前方插入一个元素elem的副本,并返回新元素的位置(此时返回的是整型,而非iterator)
6c.insert(pos,n,elem)在iterator指向的pos位置的前方插入n个元素的副本,并返回第一个新元素的位置
7c.insert(pos,beg,end)在iterator指向的pos位置的前方插入区间[beg,end)内所有元素的副本,并返回第一个新元素的位置
8c.insert(pos,initlist)在iterator指向的pos位置的前方插入初始化列表所有元素的副本,并返回第一个元素的位置(C++11新特性
9c.emplace(pos,args…)在iterator指向的pos位置的前方插入一个以args为初值的元素,并返回新元素的位置(C++11新特性
10c.emplace_back(args…)在list末尾附加一个args为初值的元素,不返回任何东西
11c.emplace_front(args…)在list首部附加一个args为初值的元素,不返回任何东西
12c.erase(pos)移除iterator位置pos上的元素,返回下一个元素的位置
13c.erase(beg,end)移除区间[beg,end)所指向的元素所有内容,返回下一个元素的位置
14c.resize(num)将list大小调整为num,若大小增大,新元素以默认构造函数或者零值进行初始化
15c.resize(num,elem)将list大小调整为num,若大小增大,新元素以elem进行初始化
16c.remove(val)移除所有值为val的元素
17c.remove_if(op)移除所有符合op(elem)为true的元素
18c.clear()移除所有元素,容器清空

  关于remove算法,举个例子,移除最后一个元素——

	list<int> l {1,2,3,4,5,6,7,8,9,9,9,9,9,9};
	l.remove(9);
	for(auto it = l.begin();it!=l.end();it++){
		cout<<*it<<" ";
	}

 
 
  • 1
  • 2
  • 3
  • 4
  • 5

在这里插入图片描述
  使用lambda语法使用remove_if算法,移除所有的偶数——

	list<int> l {1,2,3,4,5,6,7,8,9};
	l.remove_if([] (int i){
		return i%2==0;
	});
	for(auto it = l.begin();it!=l.end();it++){
		cout<<*it<<" ";
	}

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

在这里插入图片描述

list特殊函数

  由于list存储结构的特性,list还提供了STL通用标准之外的特殊函数,这些函数将list的性能发挥得淋漓尽致,熟练使用这些操作将使编程工作变得事半功倍。

序号操作效果
1c.unique()如果存在若干相邻数值相同的元素,就移除重复元素,只留一个
2c.unique(op)如果存在若干相邻元素都使op()结果为true,移除重复元素,只留一个
3c.splise(pos,c2)将c2内所有的元素转移到c之内,迭代器指向的pos位置之前
4c.splise(pos,c2,c2pos)将c2内的c2pos所指元素转移到c的pos所指位置
5splise(pos,c2,c2beg,c2end)将c2区间[beg,end)内所有的元素转移到c内的pos之前
6c,sort()以operator<定义的准则进行排序
7c.sort(op)以op()定义的准则进行排序
8c.merge(c2)假设c和c2容器都包含op()准则下的已排序元素,将c2的全部元素转移到c,并保证合并后的list依然有序
9c.merge(c2,op)在op()准则下进行合并,合并后的元素有序
10c.reverse()将所有元素逆序

  下面是关于list排序函数的举例——

#include<iostream>
#include<list>
using namespace std;

bool op(int&a,int&b){
return a>b;
}

int main(){
list<int> l {45,78,385,7,4,978,49,11};
l.sort(op);
for(auto it = l.begin();it!=l.end();it++){
cout<<*it<<" ";
}
return 0;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

在这里插入图片描述
  sort按照op函数定义的规则进行从大到小的输出,下面是一个合并的举例——

#include<iostream>
#include<list>
using namespace std;

int main(){
list<int> l {45,78,385,7,4,978,49,11};
list<int> l2 {-1,-5,-2,-4,-3};
l.merge(l2);
for(auto it = l.begin();it!=l.end();it++){
cout<<*it<<" ";
}
return 0;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

在这里插入图片描述
  可以看出list所谓的合并有序,是指l和2的相对有序,而不是整体有序。

异常处理 (Exception Handling)

  所有的STL容器中,list对异常的安全性提供了最佳支持,几乎有所的操作都是不成功便成仁:要么成功,要么无效。唯一不提供如此保证的是赋值运算和成员函数sort,不过他们也有最基本保证:抛出异常时不会泄漏资源,也不会与容器恒常特性(invariant)发生冲突。
  merge、remove、remove_if和unique提供的保证是有前提的,就是元素之间的比较动作不抛出异常。用数据库的术语来说,只要不调用赋值操作或sort,并保证元素互相比较时不抛出异常,那么list便可说是事物安全(transaction safe)。

        </div>
					<link href="https://csdnimg.cn/release/phoenix/mdeditor/markdown_views-a47e74522c.css" rel="stylesheet">
            </div>
								
				<script>
					(function(){
						function setArticleH(btnReadmore,posi){
							var winH = $(window).height();
							var articleBox = $("div.article_content");
							var artH = articleBox.height();
							if(artH > winH*posi){
								articleBox.css({
									'height':winH*posi+'px',
									'overflow':'hidden'
								})
								btnReadmore.click(function(){
									if(typeof window.localStorage === "object" && typeof window.csdn.anonymousUserLimit === "object"){
										if(!window.csdn.anonymousUserLimit.judgment()){
											window.csdn.anonymousUserLimit.Jumplogin();
											return false;
										}else if(!currentUserName){
											window.csdn.anonymousUserLimit.updata();
										}
									}
									
									articleBox.removeAttr("style");
									$(this).parent().remove();
								})
							}else{
								btnReadmore.parent().remove();
							}
						}
						var btnReadmore = $("#btn-readmore");
						if(btnReadmore.length>0){
							if(currentUserName){
								setArticleH(btnReadmore,3);
							}else{
								setArticleH(btnReadmore,1.2);
							}
						}
					})()
				</script>
  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值