C ++ list 用法整理(官网例子)

这篇博客详细介绍了C++中的list容器,包括其定义、初始化、常用函数及其使用示例,如assign、begin、erase、insert、merge等。文章强调了list由双向链表实现,无法通过下标访问,并提供了std::experimental::ostream_joiner用于便捷输出list元素。此外,还讨论了如何通过rbegin进行逆向遍历和逆向排序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

因为最近一直在用 C++ 的 list,搜到的那个最高访问的 优快云 博文写的不够简洁。而官网上的一些例子有些细节没涉及到,得自己再复制下来跑一遍才能搞明白。于是便萌生了写这篇博文的念头,方便自己以后查阅。

本文的例子都来自官网的介绍:http://www.cplusplus.com/reference/list/list/

https://en.cppreference.com/w/cpp/container/list 这个网站上的例子可以直接在线运行,修改查看起来十分方便。

可以使用 C++17 开始引入的 std::experimental::ostream_joiner 来快捷输出 list 中所有元素。使用时记得引入头文件 #include <experimental/iterator>

std::copy(std::begin(mylist),
          std::end(mylist),
          std::experimental::make_ostream_joiner(std::cout, ", "));

list 实现

list 容器是由双向链表实现的,因此不能使用下标运算符 [] 访问其中的元素

使用 list 的时候得加上 #include <list> 头文件以及得在 std 名字空间中使用。

list 定义和初始化

只需要简单的 list<TYPE> my_list; 就可以完成对一个 list 的定义了。不需要 new。

初始化的话就要用到 list 的构造函数
一个简单的例子是:

  int myints[] = {75,23,65,42,13};
  list<int> mylist (myints, myints+5);

当然我们仍然可以使用一些函数对 list 增加删除元素。

list 函数介绍

这里介绍一些我觉得可能比较常用的函数。

迭代器

函数名作用
begin将迭代器返回到开头(Return iterator to beginning)
end将迭代器返回到最后(Return iterator to end)
rbeginReturn reverse iterator to reverse beginning
rendReturn reverse iterator to reverse end

C++ 11 标准又新增 cbegin, cend, crbegin 和 crend 这四个函数,返回的都是 const_iterator。

容量

函数名作用
empty检查容器是否为空
size返回当前容器内元素个数
max_size返回当前容器能容纳的最大元素数量

元素访问

函数名作用
front访问第一个元素
back访问最后一个元素

更改 list

函数名作用
assignAssign new content to container
push_front将元素插入到开头
pop_front删除第一个元素
push_back将元素插入到最后
pop_back删除最后一个元素
insert插入元素
erase删除元素
swap交换两个 list 内容
resize改变容器大小
clear删除容器所有内容

C++ 11 标准又增加了 emplace_front, emplace_back, emplace 这三个函数

操作

函数名作用
splice合并两个 list
remove根据值删除元素
remove_if删除满足条件的元素
unique删除重复的值
merge合并排好序的 list
sort对容器内的元素排序
reverse将元素反序

函数举例

这里介绍一些函数的使用例子,加深理解。函数的排序按字典序排的,方便从目录查找跳转。

ATTENTION:程序的输出一般写在注释里。

assign()

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

template <class T>
void print_list(list<T> my_list)
{
	for (typename list<T>::iterator it = my_list.begin(); it != my_list.end(); ++it)
		cout << ' ' << *it;

	cout << '\n';
} 

int main ()
{
	list<int> first;
	list<int> second;

	first.assign (7, 100);                      // 7 ints with value 100
	print_list(first);
	// 100 100 100 100 100 100 100

	second.assign (first.begin(),first.end()); // a copy of first
	print_list(second);
	// 100 100 100 100 100 100 100

	int myints[]= {1776, 7, 4};
	first.assign (myints, myints+3);            // assigning from array
	print_list(first);
	// 1776 7 4

	cout << "Size of first: " << int (first.size()) << '\n';
	cout << "Size of second: " << int (second.size()) << '\n';
	// Size of first: 3
	// Size of second: 7
	
	return 0
}

begin() —— 对 list 进行顺序遍历

end() 的代码和这个一模一样。

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

int main ()
{
	int myints[] = {75,23,65,42,13};
	list<int> mylist (myints,myints+5);

	cout << "mylist contains:";
	for (list<int>::iterator it = mylist.begin(); it != mylist.end(); ++it)
		std::cout << ' ' << *it;

	cout << '\n';
	// mylist contains: 75 23 65 42 13
	return 0;
}

erase()——动态删除

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

int main ()
{
	list<int> mylist;
	list<int>::iterator it1,it2;

	// set some values:
	for (int i=1; i<10; ++i) mylist.push_back(i*10);

								// 10 20 30 40 50 60 70 80 90
	it1 = it2 = mylist.begin(); // ^^
	advance (it2,6);            // ^                 ^
	++it1;                      //    ^              ^

	it1 = mylist.erase (it1);   // 10 30 40 50 60 70 80 90
								//    ^           ^

	it2 = mylist.erase (it2);   // 10 30 40 50 60 80 90
								//    ^           ^

	++it1;                      //       ^        ^
	--it2;                      //       ^     ^

	mylist.erase (it1,it2);     // 10 30 60 80 90
								//        ^

	cout << "mylist contains:";
	for (it1=mylist.begin(); it1!=mylist.end(); ++it1)
		cout << ' ' << *it1;
	cout << '\n';

	return 0;
}

使用 erase() 函数,我们可以实现动态的删除。

int main ()
{
	list<int> mylist;
	
	// set some values:
	for (int i=1; i<5; ++i) mylist.push_back(i*10);
	// 10 20 30 40

	cout << "mylist contains:";
	for (list<int>::iterator it=mylist.begin(); it!=mylist.end(); ++it)
	{
		if (*it == 30)
			it = mylist.erase(it);
		cout << ' ' << *it;
	}
	cout << '\n';
	// mylist contains: 10 20 40
	
	return 0;
}

insert()——插入元素

insert 的参数还是到官网上查比较好,上面的表格里给出了链接。
下面的 ^ 表示当前的迭代器指向哪个元素。

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

int main ()
{
	list<int> mylist;
	list<int>::iterator it;

	// set some initial values:
	for (int i=1; i<=5; ++i) mylist.push_back(i); // 1 2 3 4 5

	it = mylist.begin();
	++it;       // it points now to number 2           ^

	mylist.insert (it,10);                        // 1 10 2 3 4 5

	// "it" still points to number 2                      ^
	mylist.insert (it,2,20);                      // 1 10 20 20 2 3 4 5

	--it;       // it points now to the second 20            ^

	vector<int> myvector (2,30);
	mylist.insert (it,myvector.begin(),myvector.end());
	// 1 10 20 30 30 20 2 3 4 5
	//               ^
	cout << "mylist contains:";
	for (it=mylist.begin(); it!=mylist.end(); ++it)
		cout << ' ' << *it;
	cout << '\n';
	// mylist contains: 1 10 20 30 30 20 2 3 4 5
	
	return 0;
}

merge() —— 合并两个 list

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

// compare only integral part:
bool mycomparison (double first, double second)
{
	return ( int(first)<int(second) );
}

int main ()
{

	list<double> first, second;

	first.push_back (3.1);
	first.push_back (2.2);
	first.push_back (2.9);

	second.push_back (3.7);
	second.push_back (7.1);
	second.push_back (1.4);

	first.sort();  // 2.2 2.9 3.1
	second.sort(); // 1.4 3.7 7.1

	first.merge(second); // 1.4 2.2 2.9 3.1 3.7 7.1

	// (second is now empty)

	second.push_back (2.1);  // 2.1

	first.merge(second, mycomparison);

	cout << "first contains:";
	for (list<double>::iterator it=first.begin(); it!=first.end(); ++it)
		cout << ' ' << *it;
	cout << '\n';
	// first contains: 1.4 2.2 2.9 2.1 3.1 3.7 7.1
	
	return 0;
}

但是经过我的尝试,好像可以不排序合并:

int main ()
{
	list<double> first, second;

	for (int i=1; i<=5; ++i) first.push_back(i);
	for (int i=1; i<=5; ++i) second.push_back(i+10);

	first.merge(second);
	// (second is now empty)

	cout << "first contains:";
	for (list<double>::iterator it=first.begin(); it!=first.end(); ++it)
		cout << ' ' << *it;
	cout << '\n';
	// first contains: 1 2 3 4 5 11 12 13 14 15
	
	return 0;
}

rbegin() —— 对 list 进行逆向遍历

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

int main ()
{
	list<int> mylist;
	for (int i=1; i<=5; ++i) mylist.push_back(i);

	cout << "mylist backwards:";
	for (list<int>::reverse_iterator rit=mylist.rbegin(); rit!=mylist.rend(); ++rit)
		cout << ' ' << *rit;

	cout << '\n';
	// mylist backwards: 5 4 3 2 1
	return 0;
}

利用『逆向』这个特性,我们还可以用来实现逆向排序。STL 里的 sort 默认是按自然数顺序来排序的,要想实现从大到小排序的效果,我们有三种方法:

  • 自己写比较函数
struct greater
{
    template<class T>
    bool operator()(T const &a, T const &b) const { return a > b; }
};

std::sort(numbers.begin(), numbers.end(), greater());
  • 指定比较规则
std::sort(numbers.begin(), numbers.end(), std::greater<int>());
  • 使用 rbegin()
std::sort(numbers.rbegin(), numbers.rend());   // note: reverse iterators

remove()

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

int main ()
{
	int myints[]= {17,89,7,14};
	list<int> mylist (myints,myints+4);
	// 17 89 7 14
	mylist.remove(89);
	
	cout << "mylist contains:";
	for (list<int>::iterator it=mylist.begin(); it!=mylist.end(); ++it)
		cout << ' ' << *it;
	cout << '\n';
	// mylist contains: 17 7 14

	return 0;
}

它会删除所有匹配的值,也就是说

	int myints[]= {17,89,7,89,14};
	list<int> mylist (myints,myints+5);
	// 17 89 7 89 14
	
	mylist.remove(89);
	// mylist contains: 17 7 14

如果你想像下面这样写的话,会出现死循环。

int main ()
{
	int myints[]= {17,89,7,14};
	list<int> mylist (myints,myints+4);
	// 17 89 7 14
	
	cout << "mylist contains:";
	for (list<int>::iterator it=mylist.begin(); it!=mylist.end(); ++it) {
		if (*it == 89) 
			mylist.remove(89);
		cout << ' ' << *it;
	}

	cout << '\n';
	// 死循环

	return 0;
}

想要达到上述的效果,可以使用 erase() 函数。具体代码见那一节。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值