因为最近一直在用 C++ 的 list,搜到的那个最高访问的 CSDN 博文写的不够简洁。而官网上的一些例子有些细节没涉及到,得自己再复制下来跑一遍才能搞明白。于是便萌生了写这篇博文的念头,方便自己以后查阅。
本文的例子都来自官网的介绍:http://www.cplusplus.com/reference/list/list/
list 容器是由双向链表实现的,因此不能使用下标运算符 []
访问其中的元素。
使用 list 的时候得加上 #include
头文件以及得在 std 名字空间中使用。
只需要简单的 list
就可以完成对一个 list 的定义了。不需要 new。
初始化的话就要用到 list 的构造函数。
一个简单的例子是:
int myints[] = {75,23,65,42,13};
list<int> mylist (myints, myints+5);
当然我们仍然可以使用一些函数对 list 增加删除元素。
这里介绍一些我觉得可能比较常用的函数。
函数名 | 作用 |
---|---|
begin | 将迭代器返回到开头(Return iterator to beginning) |
end | 将迭代器返回到最后(Return iterator to end) |
rbegin | Return reverse iterator to reverse beginning |
rend | Return reverse iterator to reverse end |
C++ 11 标准又新增 cbegin, cend, crbegin 和 crend 这四个函数,返回的都是 const_iterator。
函数名 | 作用 |
---|---|
empty | 检查容器是否为空 |
size | 返回当前容器内元素个数 |
max_size | 返回当前容器能容纳的最大元素数量 |
函数名 | 作用 |
---|---|
front | 访问第一个元素 |
back | 访问最后一个元素 |
函数名 | 作用 |
---|---|
assign | Assign 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:程序的输出一般写在注释里。
#include
#include
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
}
end() 的代码和这个一模一样。
#include
#include
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;
}
#include
#include
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 的参数还是到官网上查比较好,上面的表格里给出了链接。
下面的 ^
表示当前的迭代器指向哪个元素。
#include
#include
#include
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;
}
#include
#include
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;
}
#include
#include
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>());
std::sort(numbers.rbegin(), numbers.rend()); // note: reverse iterators
#include
#include
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() 函数。具体代码见那一节。