一、简介
- list是由双向链表实现的,内存空间是不连续的。由链表的实现原理可知:
优点:插入和删除非常快。只需要在插入的地方更改指针的指向即可,不用移动数据。
缺点:不支持随机访问,查询效率较低,时间复杂度为O(n)
- forward_list是一个单向链表,只支持单向顺序访问,在链表的任何位置进行插入/删除操作都非常快。
list的迭代器不支持+、-
操作,支持++、--
操作(vector迭代器支持+、-、++、--
等操作),可以使用std::advance
达到+
的目的
二、构造
// C++11 初始化列表语法:
std::list<std::string> words1{ "the", "frogurt", "is", "also", "cursed" };
// words2 == words1
std::list<std::string> words2(words1.begin(), words1.end());
// words3 == words1
std::list<std::string> words3(words1);
// words4 为 {"Mo", "Mo", "Mo", "Mo", "Mo"}
std::list<std::string> words4(5, "Mo");
三、增加元素
- insert、emplace:在某一给定位置插入元素
template <class... Args>
iterator emplace (const_iterator position, Args&&... args);
//single element(1)
iterator insert(const_iterator position, const value_type& val);
//fill(2)
iterator insert(const_iterator position, size_type n, const value_type& val);
//range(3)
template <class InputIterator>
iterator insert(const_iterator position, InputIterator first, InputIterator last);
//move(4)
iterator insert(const_iterator position, value_type&& val);
//initializer list(5)
iterator insert(const_iterator position, initializer_list<value_type> il);
- emplace_back、push_back:在容器尾部插入元素
template <class... Args>
void emplace_back (Args&&... args);
void push_back (const value_type& val);
void push_back (value_type&& val);
- emplace_front、push_front:在容器头部插入元素
template <class... Args>
void emplace_front (Args&&... args);
void push_front (const value_type& val);
void push_front (value_type&& val);
- 示例代码:
std::list<int> List1;
List1.insert(List1.begin(), { 1,2 }); //1,2
List1.emplace(List1.end(), std::move(3)); //1,2,3
List1.emplace_back(4); //1,2,3,4
List1.emplace_front(5); //5,1,2,3,4
List1.push_back(6); //5,1,2,3,4,6
List1.push_front(7); //7,5,1,2,3,4,6
四、删除元素
- clear:清空元素
void clear() noexcept;
- pop_back、pop_front:移除尾部或首部元素
如果容器为空,这两个函数会中断(不是抛出异常)
void pop_back();
void pop_front();
- erase:删除指定位置的元素
iterator erase (const_iterator position); //仅仅删除这个位置的一个元素
iterator erase (const_iterator first, const_iterator last); //删除first到last的所有元素
- remove:删除指定元素
void remove (const value_type& val);
- remove_if、erase_if(C++20):擦除所有满足特定判别标准的元素
注意:删除的是pred返回true的元素。
template< class T, class Alloc, class Pred >
typename std::list<T, Alloc>::size_type erase_if(std::list<T, Alloc>& c, Pred pred);
template <class Predicate>
void remove_if (Predicate pred);
- 示例代码:
std::list<int> List2{ 0,1,2,3,4,5,6,7,8 };
List2.pop_back(); //0,1,2,3,4,5,6,7
List2.pop_front(); //1,2,3,4,5,6,7
List2.erase(List2.begin()); //2,3,4,5,6,7
List2.erase(std::find(List2.begin(), List2.end(), 5), List2.end()); //2,3,4
List2.remove(2); //3,4
List2.remove_if([](int n) {return n == 4; }); //3
List2.clear(); //清空
五、修改元素
- 修改
list不能像vector一样通过[]
修改元素,不过可以先删除需要修改的元素,再添加一个新的元素。
- swap:交换
注意:交换的两个list类型必须相同
void swap (list& x);
- 示例代码:
std::list<int> List4{ 2,3,4 };
std::list<int> List5{ 7,8,9 };
List4.swap(List5);
std::list<int> List6{ 1,2,3,4,5,6 };
List5.remove(3);
List6.emplace_back(7);
- assign:替换原有的list的内容
和swap相比,assign功能更强大,assign的参数可以是其他容器,也可以选择将list用容器中的一部分元素替换。
list.assign(vector.begin(),vector.end());
六、访问元素、查找元素
注意:list没有自己的查找函数,如果要使用查找,可以用算法库(algorithm)中的std::find函数
-
front:访问第一个元素
-
back:访问最后一个元素
-
示例代码:
std::list<int> List3{ 1,2,3,4,5 };
int front = List3.front(); //1
int back = List3.back(); //5
std::list<int>::iterator it = std::find(List3.begin(), List3.end(), 2);
七、其他
- 排序:sort()
默认升序排序,若要使用降序排序:
升序:sort(std::less<data-type>())
降序:sort(std::greater<data-type>())
List7.sort(std::greater<int>()); //降序
List7.sort(std::less<int>()); //升序
-
逆序:reverse()
-
移除重复元素:unique()
注意:不相邻的重复元素不会被删除 -
合并:merge
前提:两个已排序的list,且必须按升序排序(list::sort()默认升序排序)
注意:归并完之后,x会被清空(即全部移动到调用对象中去)
函数原型:
void merge(list& x);
void merge(list&& x);
template <class Compare>
void merge(list& x, Compare comp);
template <class Compare>
void merge(list&& x, Compare comp);
示例代码:
std::list<int> List7{ 8,7,7,9 };
List7.sort();
std::list<int> List8{ 5,3,3,2 };
List8.sort();
List7.merge(List8);
- 转移元素:splice()
函数原型:
//entire list(1)
void splice(const_iterator position, list& x);
void splice(const_iterator position, list&& x);
//single element(2)
void splice(const_iterator position, list& x, const_iterator i);
void splice(const_iterator position, list&& x, const_iterator i);
//element range(3)
void splice(const_iterator position, list& x, const_iterator first, const_iterator last);
void splice(const_iterator position, list&& x, const_iterator first, const_iterator last);
示例代码:
std::list<int> List9{ 1,2,3,4,5 };
std::list<int> List10{ 7,8,9 };
auto it9 = List9.begin();
std::advance(it9, 2); //迭代器指向的元素向后移动两位,指向3
List9.splice(it9, List10); //List9:1,2,7,8,9,3,4,5;List10为空
std::list<int> List11{ 1,2,3 };
std::list<int> List12{ 5,6,7,8,9 };
auto it12 = List12.begin();
std::advance(it12, 2);
List11.splice(List11.begin(), List12, it12, List12.end()); //List11:7,8,9,1,2,3;Lis12:5,6
完整代码
点击查看代码
#include <iostream>
#include <algorithm>
#include <list>
int main()
{
//插入
std::list<int> List1;
List1.insert(List1.begin(), { 1,2 }); //1,2
List1.emplace(List1.end(), std::move(3)); //1,2,3
List1.emplace_back(4); //1,2,3,4
List1.emplace_front(5); //5,1,2,3,4
List1.push_back(6); //5,1,2,3,4,6
List1.push_front(7); //7,5,1,2,3,4,6
//删除
std::list<int> List2{ 0,1,2,3,4,5,6,7,8 };
List2.pop_back(); //0,1,2,3,4,5,6,7
List2.pop_front(); //1,2,3,4,5,6,7
List2.erase(List2.begin()); //2,3,4,5,6,7
List2.erase(std::find(List2.begin(), List2.end(), 5), List2.end()); //2,3,4
List2.remove(2); //3,4
List2.remove_if([](int n) {return n == 4; }); //3
List2.clear(); //清空
//查找
std::list<int> List3{ 1,2,3,4,5 };
int front = List3.front(); //1
int back = List3.back(); //5
std::list<int>::iterator it = std::find(List3.begin(), List3.end(), 2);
//修改
std::list<int> List4{ 2,3,4 };
std::list<int> List5{ 7,8,9 };
List4.swap(List5);
std::list<int> List6{ 1,2,3,4,5,6 };
List5.remove(3);
List6.emplace_back(7);
//归并
std::list<int> List7{ 8,7,7,9 };
List7.sort();
std::list<int> List8{ 5,3,3,2 };
List8.sort();
List7.merge(List8);
//排序
List7.sort(std::greater<int>()); //降序
List7.sort(std::less<int>()); //升序
//移除相邻重复元素
List7.unique();
//逆序
List7.reverse();
//转移元素
std::list<int> List9{ 1,2,3,4,5 };
std::list<int> List10{ 7,8,9 };
auto it9 = List9.begin();
std::advance(it9, 2); //迭代器指向的元素向后移动两位,指向3
List9.splice(it9, List10); //List9:1,2,7,8,9,3,4,5;List10为空
std::list<int> List11{ 1,2,3 };
std::list<int> List12{ 5,6,7,8,9 };
auto it12 = List12.begin();
std::advance(it12, 2);
List11.splice(List11.begin(), List12, it12, List12.end()); //List11:7,8,9,1,2,3;Lis12:5,6
return 0;
}