文章目录
一. list介绍
1). list是可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代。
2). list的底层是双向链表结构,双向链表中每个元素存储在互不相关的独立节点中,在节点中通过指针指向其前一个元素和后一个元素。
3). list与forward_list非常相似:最主要的不同在于forward_list是单链表,只能朝后迭代,已让其更简单高效。
4).与其他的序列式容器相比(array,vector,deque),list通常在任意位置进行插入、移除元素的执行效率更好。
5). 与其他序列式容器相比,list和forward_list最大的缺陷是不支持任意位置的随机访问,比如:要访问list的第6个元素,必须从已知的位置(比如头部或者尾部)迭代到该位置,在这段位置上迭代需要线性的时间开销;list还需要一些额外的空间,以保存每个节点的相关联信息(对于存储类型较小元素的大list来说这可能是一个重要的因素)
二. list使用
constructor
1).构造一个空容器
list<int> lt;
2).构造一个含有n个值为val的容器
list<int> lt(10,5);
3).拷贝构造
list<int> lt2(lt);
4). 迭代器区间构造
int a[] = { 16,2,77,29 };
list<int> lt2(a,a + 4);
/* while(first != last)
* {
* push_back(*first);
* ++first;
* }
*/
print(lt2);
// swap,find,reverse,sort 常用的算法 <algorithm>
// 原生指针可以看作天然的迭代器
sort(a,a + 4);
sort(a, a + 4, greater<int>());
// sort排序底层是快速排序,迭代器类型只能是随机迭代器
// 比如三数取中优化,lt不支持随机访问
sort(lt.begin(),lt.end());
list迭代器是双向迭代器,不支持 - 操作,因此报错
这里顺便介绍一下迭代器的类型 :
单向迭代器 : 只能向后依次遍历(只支持++操作) (如 forward_list)
双向迭代器 : 可以向前向后依次遍历(支持++和–操作) (如 list)
随机迭代器 : 可以向前向后随机遍历(支持++ /- - / + / - / += / -= 操作) (如 vector/string)
iterator
iterator begin();
const_iterator begin() const;
iterator end();
const_iterator end() const;
reverse_iterator rbegin();
const_reverse_iterator rbegin() const;
reverse_iterator rend();
const_reverse_iterator rend() const;
#include <iostream>
#include <list>
using namespace std;
int main()
{
list<int> lt(10, 5);
//正向迭代器遍历容器
list<int>::iterator it = lt.begin();
while (it != lt.end())
{
cout << *it << " ";
it++;
}
cout << endl;
// 反向迭代器遍历容器
list<int>::reverse_iterator rit = lt.rbegin();
while (rit != lt.rend())
{
cout << *rit << " ";
rit++;
}
cout << endl;
return 0;
}
capacity
empty
判断容器是否为空
#include <iostream>
#include <list>
using namespace std;
int main()
{
list<int> lt;
cout << lt.empty() << endl; //1
return 0;
}
size
获取容器中的元素个数
#include <iostream>
#include <list>
using namespace std;
int main()
{
list<int> lt;
lt.push_back(1);
lt.push_back(2);
lt.push_back(3);
lt.push_back(4);
cout << lt.size() << endl; //4
return 0;
}
Element access
front/back
front函数用于获取list容器当中的第一个元素的引用,back函数用于获取list容器当中的最后一个元素的引用
#include <iostream>
#include <list>
using namespace std;
int main()
{
list<int> lt;
lt.push_back(1);
lt.push_back(2);
lt.push_back(3);
lt.push_back(4);
cout << lt.front() << endl; //1
cout << lt.back() << endl; //4
return 0;
}
Modifiers
assign
将新内容赋值给list容器,替换其当前内容,并相应地修改其大小
1). 将n个值为val的数据分配给容器。
2). 将所给迭代器区间当中的内容分配给容器。
// list::assign
#include <iostream>
#include <list>
using namespace std;
int main ()
{
list<int> first;
list<int> second;
first.assign (7,100); // 7 ints with value 100
second.assign (first.begin(),first.end()); // a copy of first
int myints[]={1776,7,4};
first.assign (myints,myints+3); // assigning from array
cout << "Size of first: " << int (first.size()) << endl; // 3
cout << "Size of second: " << int (second.size()) << endl; // 7
return 0;
}
push_front/pop_front
头插,头删容器中的数据
#include <iostream>
#include <list>
using namespace std;
int main ()
{
list<int> mylist (2,100); // two ints with a value of 100
mylist.push_front (200);
mylist.push_front (300);
cout << "mylist contains:";
for (list<int>::iterator it=mylist.begin(); it!=mylist.end(); ++it)
cout << ' ' << *it;
cout << endl;
return 0;
// output
// 300 200 100 100
}
#include <iostream>
#include <list>
using namespace std;
int main ()
{
list<int> mylist;
mylist.push_back (100);
mylist.push_back (200);
mylist.push_back (300);
cout << "Popping out the elements in mylist:";
while (!mylist.empty())
{
cout << ' ' << mylist.front();
mylist.pop_front();
}
cout << "\nFinal size of mylist is " << mylist.size() << endl;
return 0;
// output
// Popping out the elements in mylist: 100 200 300
// Final size of mylist is 0
}
push_back/pop_back
尾插,尾删容器中的数据
// list::push_back
#include <iostream>
#include <list>
int main ()
{
std::list<int> mylist;
int myint;
std::cout << "Please enter some integers (enter 0 to end):\n";
do {
std::cin >> myint;
mylist.push_back (myint);
} while (myint);
std::cout << "mylist stores " << mylist.size() << " numbers.\n";
return 0;
}
// list::pop_back
#include <iostream>
#include <list>
int main ()
{
std::list<int> mylist;
int sum (0);
mylist.push_back (100);
mylist.push_back (200);
mylist.push_back (300);
while (!mylist.empty())
{
sum+=mylist.back();
mylist.pop_back();
}
std::cout << "The elements of mylist summed " << sum << '\n';
return 0;
// output
// The elements of mylist summed 600
}
insert
1).在指定迭代器位置插入一个数。
2). 在指定迭代器位置插入n个值为val的数。
3).在指定迭代器位置插入一段迭代器区间(左闭右开)。
// inserting into a list
#include <iostream>
#include <list>
#include <vector>
int main ()
{
std::list<int> mylist;
std::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 ^
std::vector<int> myvector (2,30);
mylist.insert (it,myvector.begin(),myvector.end());
// 1 10 20 30 30 20 2 3 4 5
// ^
std::cout << "mylist contains:";
for (it=mylist.begin(); it!=mylist.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
return 0;
// output
// mylist contains: 1 10 20 30 30 20 2 3 4 5
}
#include <iostream>
#include <list>
int main()
{
list<int> lt;
lt.push_back(1);
lt.push_back(2);
lt.push_back(3);
lt.push_back(4);
list<int>::iterator pos = find(lt.begin(),lt.end(),3);
lt.insert(pos,30);
print(lt);
cout << *pos << endl; // 3
}
insert 不会导致迭代器失效,因为链表的插入并不会影响 it/pos 所指向的位置
erase
1).删除指定迭代器位置的元素。
2). 删除指定迭代器区间(左闭右开)的所有元素。
// erasing from list
#include <iostream>
#include <list>
int main ()
{
std::list<int> mylist;
std::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
// ^
// it1 已经失效
std::cout << "mylist contains:";
for (it1=mylist.begin(); it1!=mylist.end(); ++it1)
std::cout << ' ' << *it1;
std::cout << '\n';
return 0;
// Output:
// mylist contains: 10 30 60 80 90
}
#include <iostream>
#include <list>
using namespace std;
int main()
{
list<int> lt;
lt.push_back(1);
lt.push_back(2);
lt.push_back(3);
lt.push_back(4);
list<int>::iterator pos = find(lt.begin(), lt.end(), 3);
// pos迭代器失效
lt.erase(pos);
print(lt);
cout << *pos << endl;
}
erase 会导致迭代器失效,因为链表的删除会使 pos 所指向的位置被释放,从而 pos 成为野指针
swap
swap用于交换两个容器的内容
// swap lists
#include <iostream>
#include <list>
int main ()
{
std::list<int> first (3,100); // three ints with a value of 100
std::list<int> second (5,200); // five ints with a value of 200
first.swap(second);
std::cout << "first contains:";
for (std::list<int>::iterator it=first.begin(); it!=first.end(); it++)
std::cout << ' ' << *it;
std::cout << '\n';
std::cout << "second contains:";
for (std::list<int>::iterator it=second.begin(); it!=second.end(); it++)
std::cout << ' ' << *it;
std::cout << '\n';
return 0;
// Output:
// first contains: 200 200 200 200 200
// second contains: 100 100 100
}
resize
1). 若 n 小于当前容器的 size ,size 减少到 n
2). 若 n 大于当前容器的 size,尾插入数据直到 n,值用 val 来填充
// resizing list
#include <iostream>
#include <list>
int main ()
{
std::list<int> mylist;
// set some initial content:
for (int i=1; i<10; ++i) mylist.push_back(i);
mylist.resize(5);
mylist.resize(8,100);
mylist.resize(12);
std::cout << "mylist contains:";
for (std::list<int>::iterator it=mylist.begin(); it!=mylist.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
return 0;
// output
// mylist contains: 1 2 3 4 5 100 100 100 0 0 0 0
}
clear
清空容器,使容器的 size 成为 0
// clearing lists
#include <iostream>
#include <list>
int main ()
{
std::list<int> mylist;
std::list<int>::iterator it;
mylist.push_back (100);
mylist.push_back (200);
mylist.push_back (300);
std::cout << "mylist contains:";
for (it=mylist.begin(); it!=mylist.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
mylist.clear();
mylist.push_back (1101);
mylist.push_back (2202);
std::cout << "mylist contains:";
for (it=mylist.begin(); it!=mylist.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
return 0;
// output
// mylist contains: 100 200 300
// mylist contains: 1101 2202
}
operations
splice
splice函数用于两个list容器数据之间的转移,其有三种拼接方式:
1).将整个容器拼接到另一个容器的指定迭代器位置。
2).将容器当中的某一个数据拼接到另一个容器的指定迭代器位置。
3).将容器指定迭代器区间的数据拼接到另一个容器的指定迭代器位置。
// splicing lists
#include <iostream>
#include <list>
int main ()
{
std::list<int> mylist1, mylist2;
std::list<int>::iterator it;
// set some initial values:
for (int i=1; i<=4; ++i)
mylist1.push_back(i); // mylist1: 1 2 3 4
for (int i=1; i<=3; ++i)
mylist2.push_back(i*10); // mylist2: 10 20 30
it = mylist1.begin();
++it; // points to 2
mylist1.splice (it, mylist2); // mylist1: 1 10 20 30 2 3 4
// mylist2 (empty)
// "it" still points to 2 (the 5th element)
mylist2.splice (mylist2.begin(),mylist1, it);
// mylist1: 1 10 20 30 3 4
// mylist2: 2
// "it" is now invalid.
it = mylist1.begin();
std::advance(it,3); // "it" points now to 30
mylist1.splice ( mylist1.begin(), mylist1, it, mylist1.end());
// mylist1: 30 3 4 1 10 20
std::cout << "mylist1 contains:";
for (it=mylist1.begin(); it!=mylist1.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
std::cout << "mylist2 contains:";
for (it=mylist2.begin(); it!=mylist2.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
return 0;
// output
// mylist1 contains: 30 3 4 1 10 20
// mylist2 contains: 2
}
remove
remove函数用于删除容器当中被指定的元素,和erase不同,erase是删除迭代器位置的值
// remove from list
#include <iostream>
#include <list>
int main ()
{
int myints[] = {17,89,7,14};
std::list<int> mylist (myints,myints+4);
mylist.remove(89);
std::cout << "mylist contains:";
for (std::list<int>::iterator it=mylist.begin(); it!=mylist.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
return 0;
// Output:
// mylist contains: 17 7 14
}
remove_if
remove_if函数用于删除容器当中满足条件的元素。
// list::remove_if
#include <iostream>
#include <list>
// a predicate implemented as a function:
bool single_digit (const int& value) { return (value<10); }
// a predicate implemented as a class:
struct is_odd {
bool operator() (const int& value) { return (value%2)==1; }
};
int main ()
{
int myints[]= {15,36,7,17,20,39,4,1};
std::list<int> mylist (myints,myints+8); // 15 36 7 17 20 39 4 1
mylist.remove_if (single_digit); // 15 36 17 20 39
mylist.remove_if (is_odd()); // 36 20
std::cout << "mylist contains:";
for (std::list<int>::iterator it=mylist.begin(); it!=mylist.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
return 0;
// Output:
// mylist contains: 36 20
}
unique
unique函数用于删除容器当中连续的重复元素(配合sort使用)。
// list::unique
#include <iostream>
#include <cmath>
#include <list>
// a binary predicate implemented as a function:
bool same_integral_part (double first, double second)
{ return ( int(first)==int(second) ); }
// a binary predicate implemented as a class:
struct is_near {
bool operator() (double first, double second)
{ return (fabs(first-second)<5.0); }
};
int main ()
{
double mydoubles[]={ 12.15, 2.72, 73.0, 12.77, 3.14,
12.77, 73.35, 72.25, 15.3, 72.25 };
std::list<double> mylist (mydoubles,mydoubles+10);
mylist.sort(); // 2.72, 3.14, 12.15, 12.77, 12.77,
// 15.3, 72.25, 72.25, 73.0, 73.35
mylist.unique(); // 2.72, 3.14, 12.15, 12.77
// 15.3, 72.25, 73.0, 73.35
mylist.unique (same_integral_part); // 2.72, 3.14, 12.15
// 15.3, 72.25, 73.0
mylist.unique (is_near()); // 2.72, 12.15, 72.25
std::cout << "mylist contains:";
for (std::list<double>::iterator it=mylist.begin(); it!=mylist.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
return 0;
// mylist contains: 2.72 12.15 72.25
}
sort
sort 默认将容器中的数据排成升序,排降序可以用 greater<>
// list::sort
#include <iostream>
#include <list>
#include <string>
#include <cctype>
// comparison, not case sensitive.
bool compare_nocase (const std::string& first, const std::string& second)
{
unsigned int i=0;
while ( (i<first.length()) && (i<second.length()) )
{
if (tolower(first[i])<tolower(second[i])) return true;
else if (tolower(first[i])>tolower(second[i])) return false;
++i;
}
return ( first.length() < second.length() );
}
int main ()
{
std::list<std::string> mylist;
std::list<std::string>::iterator it;
mylist.push_back ("one");
mylist.push_back ("two");
mylist.push_back ("Three");
mylist.sort();
std::cout << "mylist contains:";
for (it=mylist.begin(); it!=mylist.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
mylist.sort(compare_nocase);
std::cout << "mylist contains:";
for (it=mylist.begin(); it!=mylist.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
return 0;
// mylist contains: Three one two
// mylist contains: one Three two
}
reverse
reverse函数用于将容器当中元素的位置进行逆置。
// reversing list
#include <iostream>
#include <list>
int main ()
{
std::list<int> mylist;
for (int i=1; i<10; ++i) mylist.push_back(i);
mylist.reverse();
std::cout << "mylist contains:";
for (std::list<int>::iterator it=mylist.begin(); it!=mylist.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
return 0;
// mylist contains: 9 8 7 6 5 4 3 2 1
}