C++知识点23——使用C++标准库(顺序容器list的其他操作)

除了博客https://blog.csdn.net/Master_Cui/article/details/107751785中介绍的操作,list还有一些其他的操作

 

1.reverse

void reverse();

这个最为简单,作用是反转list

 

示例

void reversetest()
{
	list<int> l={1,2,3,4,5,6,7};
	l.reverse();
	for (list<int>::iterator it=l.begin();
		it!=l.end();++it) {
		cout<<*it<<",";
	}
	cout<<endl;
}

 

2.sort

void sort();
	
template <class Compare>
void sort (Compare comp);

这个也较为简单,作用是对list中的元素进行排序

 

示例1

void sorttest()
{
	list<int> l={1,3,5,7, 2, 4,6,8};
	l.sort();
	for (list<int>::iterator it=l.begin();
		it!=l.end();++it) {
		cout<<*it<<",";
	}
	cout<<endl;
}

第二个重载函数为list排序指定了规则,comp可以为函数指针,函数对象以及lambada表达式

而且comp必须为严格弱序,简单来说,严格弱序就是comp的实现中,如果两个元素相等,要返回false,次序保持不变。

具体原因后续再说

 

示例2

bool comp(int a, int b) {return a>b;}
void sorttest2()
{
	list<int> l{1,3,5,7, 2, 4,6,8};
	l.sort(comp);
	for (list<int>::iterator it=l.begin();
		it!=l.end();++it) {
		cout<<*it<<",";
	}
	cout<<endl;
}

上述的comp就是一个严格弱序的比较函数(因为当a与b相等时,返回false,如果加了等号,那么就不是严格弱序),因为list按照comp返回值为true的条件进行排序,所以排序后,list中每个元素都比后面的元素要大,所以排序后结果是降序的

 

3.merge

void merge (list& x);

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

作用是合并两个有序的list对象合并完之后,调用对象也是有序的同时list对象x中的元素都被移动到了调用对象中

 

示例1

void mergetest()
{
	list<int> l1={1,3,5,7};
	list<int> l2={2,4,6,8};
	l1.merge(l2);
	for (list<int>::iterator it=l1.begin();
		it!=l1.end();++it) {
		cout<<*it<<",";
	}
	cout<<endl;

	for (list<int>::iterator it=l2.begin();
		it!=l2.end();++it) {
		cout<<*it<<",";
	}
	cout<<endl;
}

通过结果可知,merge函数将l1与l2合并,并将l2中的元素都移动到了l1中,l2变为空

 

使用merge函数时,要求两个list对象都是已经排好序的,如果list对象不排序,程序将崩溃

示例2

void mergetest()
{
	list<int> l1={1,3,5,7};
	list<int> l2={4,2,6,8};
	l1.merge(l2);
	for (list<int>::iterator it=l1.begin();
		it!=l1.end();++it) {
		cout<<*it<<",";
	}
	cout<<endl;

	for (list<int>::iterator it=l2.begin();
		it!=l2.end();++it) {
		cout<<*it<<",";
	}
	cout<<endl;
}

所以在使用list的merge方法时,先使用sort方法将list排好序,然后再调用merge

 

merge方法也可以使用函数指针或者函数对象或者lambda表达式来规定合并两个有序list对象的规则,同样,comp也必须是严格弱序

示例3

bool isodd1(int a, int b)
{
	return a %2==0 && b%2!=0;
}
void mergetest2()
{
	list<int> l1={3,1,7,5};
	list<int> l2={4,2,8,6};
	l1.sort();
	l2.sort();
	l1.merge(l2,isodd1);
	for (list<int>::iterator it=l1.begin();
		it!=l1.end();++it) {
		cout<<*it<<",";
	}
	cout<<endl;

	for (list<int>::iterator it=l2.begin();
		it!=l2.end();++it) {
		cout<<*it<<",";
	}
	cout<<endl;
}

上述代码中,首先合并list对象前,对list对象进行排序,然后按照函数isodd1中的规则对l2进行合并,如果a是偶数并且b是奇数,那么将a和b的位置调换

所以最终偶数在前,奇数在后

同时,merge后,将l2中的元素都移动到了l1中,l2变为空

 

合并过程如下

1 3 5 7->2 1 3 5 7->2 4 1 3 5 7->2 4 6 1 3 5 7->2 4 6 8 1 3 5 7

每次merge时,如果第一次发现满足isodd1的条件,就直接执行merge

 

4.splice

void splice (iterator position, list& x);
//将list对象x拼接到调用对象的迭代器位置position,splice后,将x中的元素移动到调用对象中,见示例1

void splice (iterator position, list& x, iterator i);
//将x中迭代器位置i指向的元素拼接到调用对象中迭代器位置position,splice后,将x中的迭代器位置i指向的元素移动到调用对象中,见示例2

void splice (iterator position, list& x, iterator first, iterator last);
//将l2中迭代器范围内的元素移动到调用对象中,见示例3

splice函数的作用是拼接两个list对象,和merge类似,只不过splice不要求链表有序,而且可以部分拼接

 

示例1

void splicetest()
{
	list<int> l1={3,1,7,5};
	list<int> l2={4,2,8,6};
	l1.splice(++l1.begin(), l2);//将l2中的所有元素移动到l1的++l1.begin()位置,拼接后,l2为空
	for (list<int>::iterator it=l1.begin();
		it!=l1.end();++it) {
		cout<<*it<<",";
	}
	cout<<endl;

	for (list<int>::iterator it=l2.begin();
		it!=l2.end();++it) {
		cout<<*it<<",";
	}
	cout<<endl;
}

 

示例2

void splicetest2()
{
	list<int> l1={3,1,7,5};
	list<int> l2={4,2,8,6};
	l1.splice(++l1.begin(), l2, ++l2.begin());//将l2中 ++l2.begin()指向的元素2移动到l1中的++l1.begin()的位置
	for (list<int>::iterator it=l1.begin();
		it!=l1.end();++it) {
		cout<<*it<<",";
	}
	cout<<endl;

	for (list<int>::iterator it=l2.begin();
		it!=l2.end();++it) {
		cout<<*it<<",";
	}
	cout<<endl;
}

 

示例3

void splicetest2()
{
	list<int> l1={3,1,7,5};
	list<int> l2={4,2,8,6};
	l1.splice(++l1.begin(), l2, ++l2.begin(), --l2.end());
	for (list<int>::iterator it=l1.begin();
		it!=l1.end();++it) {
		cout<<*it<<",";
	}
	cout<<endl;

	for (list<int>::iterator it=l2.begin();
		it!=l2.end();++it) {
		cout<<*it<<",";
	}
	cout<<endl;
}

 

5.unique

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

函数的作用:如果list对象中有连续重复的元素,那么只保留第一个连续重复的元素,将剩余的连续重复元素删除,如果没有连续重复的元素,不删除该元素

 

示例1

void uniquetest()
{
	list<int> l1={1,1,2,2,3,3,1,1,2,3};
	l1.unique();
	for (list<int>::iterator it=l1.begin();
		it!=l1.end();++it) {
		cout<<*it<<",";
	}
	cout<<endl;
}

通过上面的例子可以知道,unique并不能去重,只是删除连续重复的元素并将第一个连续重复的元素保留,如果向去重,需要先排序

 

同样,和sort,merge类似,也可以指定unique的规则,同样需要保证严格弱序

示例2

bool comp(int a, int b) {return a<b;}
void uniquetest()
{
	list<int> l1={1,1,2,2,3,3,1,1,2,3};
	l1.unique(comp2);
	for (list<int>::iterator it=l1.begin();
		it!=l1.end();++it) {
		cout<<*it<<",";
	}
	cout<<endl;
}

删除过程如下;

1, 1 , 2, 2, 3, 3, 1, 1, 2, 3(发现1和1不满足comp,所以保留第二个1)->1, 1, 2, 2, 3, 3, 1, 1, 2, 3(发现1和2满足comp,所以删除第1

^  ^                                                                                                                                     ^  ^

个2)->1, 1, 2, 3, 3, 1, 1, 2, 3(发现1和2满足comp,所以删除第2个2)->1, 1, 3, 3, 1, 1, 2, 3(发现1和3满足comp,所以删除第1个3)

                 ^  ^                                                                                                                    ^  ^

->1, 1, 3, 1, 1, 2, 3(发现1和3满足comp,所以删除第2个3)->1, 1, 1, 1, 2, 3(发现1和1不满足comp,所以保留第1个1)->

         ^  ^                                                                                                          ^  ^

1, 1, 1, 1, 2, 3(发现1和1不满足comp,所以保留第2个1)->1, 1, 1, 1, 2, 3(发现1和2满足comp,所以删除2)->

         ^  ^                                                                                                               ^  ^

1, 1, 1, 1, 3(发现1和3满足comp,所以删除3)->1, 1, 1, 1

               ^  ^                                                                                                          

 

参考

《C++ Primer》

《C++标准库》

http://www.cplusplus.com/reference/list/list/

https://blog.csdn.net/jiange_zh/article/details/78240806

 

欢迎大家评论交流,作者水平有限,如有错误,欢迎指出

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值