1. 简介
list是一个容器,其结构为双向链表,支持从任何位置插入和删除元素,但不支持快速的随机访问,空间效率较低;与forward_list相比,该容器提供了双向迭代功能;
头文件和定义
//头文件
#include <list>
//定义
template<
class T,
class Allocator = std::allocator<T>
> class list;
2. 初始化
初始化分为直接初始化,拷贝初始化和赋值初始化;
/*
* @brief list
* g++ -g list_main.cc -o d -std=c++11
*
*/
#include <iostream>
#include <list>
#include <string>
//可以给类型启一个类型别名
//using list_type = std::list<int32_t>;
//using list_str_type = std::list<std::string>;
template<typename T>
void showInfo(T &t)
{
for(auto &au : t)
{
std::cout<<au<<" ";
}
std::cout<<std::endl<<std::endl;
}
int main(int argc, char *argv[])
{
std::list<int32_t> ll_1;
ll_1 = {11,21,31,41,51,61};
showInfo(ll_1);
std::list<int32_t> ll_2{100,200,300};
showInfo(ll_2);
std::list<int32_t> ll_3 = ll_1;
showInfo(ll_3);
std::list<std::string> ll_4 = {"c++","c","python","shell"};
showInfo(ll_4);
return 0;
}
输出
11 21 31 41 51 61
100 200 300
11 21 31 41 51 61
c++ c python shell
3. 使用
3.1 元素的访问
list不支持下标访问,例如at()和[]
方法 | 说明 |
---|---|
front | 链表头元素 |
back | 链表尾元素 |
iterator | 迭代器访问元素 |
示例
int main(int argc, char *argv[])
{
//1.元素的访问
std::list<std::string> ll_1 = {"c++","c","python","shell"};
std::cout<<ll_1.front()<<std::endl; //头元素
std::cout<<ll_1.back()<<std::endl<<std::endl; //尾元素
//2.迭代器
std::list<std::string>::iterator iter = ll_1.begin();
//auto iter = ll_1.begin()
while(iter != ll_1.end())
{
std::cout<<*iter<<" ";
iter++;
}
std::cout<<std::endl;
return 0;
}
结果
c++
shell
c++ c python shell
3.2 元素的大小
方法 | 说明 |
---|---|
empty | 数组判空 |
size | 数组大小 |
max_size | 最大容量 |
resize | 改变大小 |
clear | 清空size大小 |
swap | 交换两个list的内容 |
示例
int main(int argc, char *argv[])
{
//1.size empty max_size
std::list<std::string> ll_1 = {"c++","c","python","shell"};
std::cout<<ll_1.size()<<std::endl;
std::cout<<ll_1.max_size()<<std::endl<<std::endl;
if(ll_1.empty())
{
std::cout<<"list is empty."<<std::endl;
}
else{
std::cout<<"list is not empty."<<std::endl;
}
std::cout<<std::endl;
//2.resize
ll_1.resize(100);
std::cout<<"【resize test】"<<std::endl;
std::cout<<ll_1.size()<<std::endl;
std::cout<<ll_1.max_size()<<std::endl<<std::endl;
//3.swap
std::list<std::string> ll_2{"R","rust"};
std::cout<<"【swap test before】"<<std::endl;
showInfo(ll_1);
showInfo(ll_2);
ll_1.swap(ll_2);
std::cout<<"【swap test after】"<<std::endl;
showInfo(ll_1);
showInfo(ll_2);
//4.clear
ll_1.clear();
std::cout<<"ll_1 size is: "<<ll_1.size()<<std::endl;
return 0;
}
结果
4
384307168202282325
list is not empty.
【resize test】
100
384307168202282325
【swap test before】
c++ c python shell
R rust
【swap test after】
R rust
c++ c python shell
ll_1 size is: 0
3.3 元素的修改
主要包括元素的赋值、插入和删除
方法 | 说明 |
---|---|
assign | 重新对list赋值 |
= | 直接赋值 |
get_allocator | 返回内存分配器 |
insert | 插入元素,可以是任意位置,可以插入多个元素 |
emplace | 插入元素,可以是任意位置,只能插入一个元素 |
push_back | 尾部插入元素,先复制元素,在将元素插入到尾部 |
emplace_back | 尾部插入元素,直接在数组尾部创建元素 |
push_front | 头部插入元素,先复制元素,在将元素插入到头部 |
emplace_front | 头部插入元素,直接在数组尾部创建元素 |
erase | 删除元素,可以是任意位置 |
pop_back | 删除队尾元素 |
pop_front | 删除头部元素 |
示例
int main(int argc, char *argv[])
{
//1.赋值 assign 和 =
std::list<std::string> ll_1 = {"c++","c","python","shell"};
ll_1.assign(4,"test");
showInfo(ll_1);
std::cout<<std::endl;
//赋值
ll_1 = {"c++","c"};
showInfo(ll_1);
auto au = ll_1.get_allocator(); //get_allocator,返回内存适配器
std::cout<<std::endl;
//2.插入元素 insert emplace push_back emplace_back push_front emplace_front
//任何位置元素插入,需要借助迭代器
ll_1.insert(ll_1.begin(),"linux");
ll_1.emplace(ll_1.begin(),"R");
showInfo(ll_1);
std::cout<<std::endl;
//尾部元素插入
ll_1.push_back("python");
ll_1.emplace_back("shell");
showInfo(ll_1);
std::cout<<std::endl;
//头部元素插入
ll_1.push_front("golang");
ll_1.emplace_front("glog");
showInfo(ll_1);
std::cout<<std::endl;
//3.删除元素 erase pop_back pop_front
ll_1.pop_back(); //删除尾部元素
ll_1.pop_front(); //删除头部元素
showInfo(ll_1);
std::cout<<std::endl;
ll_1.erase(ll_1.begin()); //删除头部元素
ll_1.erase((--ll_1.end())); //删除尾部元素
showInfo(ll_1);
return 0;
}
结果
test test test test
c++ c
R linux c++ c
R linux c++ c python shell
glog golang R linux c++ c python shell
golang R linux c++ c python
R linux c++ c
3.4 元素的操作
方法 | 说明 |
---|---|
merge | 将list2以递增的顺序合并两个list1中,list1中的元素不会进行排序 |
splice | 剪贴函数,将list1中的元素剪贴到list2中 |
remove | 删除指定值的元素 |
remove_if | 删除指定条件的元素 |
reverse | 反序 |
unique | 去重 |
sort | 排序 |
示例
int main(int argc, char *argv[])
{
//1.merge 将list2以递增的顺序合并两个list1中
std::list<int32_t> ll_1{23,4,5,6,12};
std::list<int32_t> ll_2{3,1,45,46,72};
ll_1.merge(ll_2); //使用之前,各自应该先排序
showInfo(ll_1);
std::cout<<std::endl;
//2.splice 剪贴函数,将list1中的元素剪贴到list2中
std::cout<<"【splice】"<<std::endl;
ll_1 = {1,2,3,4,5};
ll_2 = {11,12,13,14};
auto iter = ll_1.begin();
std::advance(iter,2); //移动迭代器
ll_1.splice(iter,ll_2); //将ll_2的元素插入到ll_1中,此时ll_2为空
showInfo(ll_1);
std::cout<<std::endl;
std::list<int32_t> ll_3 = {1,2,3,4,5};
std::list<int32_t> ll_4 = {11,12,13,14};
auto iter_3 = ll_3.begin();
auto iter_4 = ll_4.begin();
std::advance(iter_3, 1);
std::advance(iter_4, 1);
ll_3.splice(iter_3, ll_4, iter_4); //将iter_4处的元素插入到ll_3的iter_3处
showInfo(ll_3);
std::cout<<std::endl;
std::list<int32_t> ll_5 = {1,2,3,4,5};
std::list<int32_t> ll_6 = {11,12,13,14};
auto iter_5 = ll_5.begin();
auto iter_6 = ll_6.begin();
std::advance(iter_5, 1);
std::advance(iter_6, 2);
ll_5.splice(iter_5, ll_6,ll_6.begin(), iter_6); //将ll_6中begin()到iter_6处的元素插入到ll_5的iter_5处
showInfo(ll_5);
std::cout<<std::endl;
//3.remove remove_if
std::cout<<"【remove】"<<std::endl;
ll_5.remove(5); //删除值为5的元素
showInfo(ll_5);
ll_5.remove_if([](int32_t n){return n > 3;}); //删除值大于3的元素
showInfo(ll_5);
std::cout<<std::endl;
//4.reverse 反序
std::cout<<"【reverse】"<<std::endl;
std::list<int32_t> ll_7 = {3,4,5,6,1,2,7,8};
ll_7.reverse();
showInfo(ll_7);
std::cout<<std::endl;
//5.unique 去重
std::cout<<"【unique】"<<std::endl;
std::list<int32_t> ll_8 {1,1,1,1,2,2,4,4,5,5};
ll_8.unique();
showInfo(ll_8);
std::cout<<std::endl;
//6.sort
std::cout<<"【sort】"<<std::endl;
ll_7.sort();
showInfo(ll_7);
return 0;
}
结果
3 1 23 4 5 6 12 45 46 72
【splice】
1 2 11 12 13 14 3 4 5
1 12 2 3 4 5
1 11 12 2 3 4 5
【remove】
1 11 12 2 3 4
1 2 3
【reverse】
8 7 2 1 6 5 4 3
【unique】
1 2 4 5
【sort】
1 2 3 4 5 6 7 8
3.5 迭代器
迭代器最好结合STL中的算法一起使用;迭代器的返回值最好用auto接受;
迭代器的类型包括:iterator、const_iterator、reverse_iterator和const_reverse_iterator
方法 | 说明 |
---|---|
begin | 返回list的头元素(迭代器),其值可修改 |
end | 返回list的尾元素(迭代器),其值可修改 |
cbegin | 返回list的头元素(迭代器),其值不可修改,const属性 |
cend | 返回list的尾元素(迭代器),其值不可修改,const属性 |
rbegin | 反序返回list的头元素(迭代器),其值可修改,同end() |
rend | 反序返回list的尾元素(迭代器),其值可修改,同begin() |
crbegin | 反序返回list的头元素(迭代器),其值不可修改,同cend,const属性 |
crend | 反序返回list的头元素(迭代器),其值不可修改,同cbegin,const属性 |
迭代器的使用大同小异,和array的使用类似
迭代器的辅助函数
辅助函数的使用需要包含头文件
#include <iterator>
方法 | 说明 |
---|---|
advance | 移动迭代器的位置 |
distance | 计算两个迭代器的距离 |
begin | 返回容器第一个元素的迭代器 |
end | 返回容器最后一个元素的迭代器 |
prev | 迭代器向前移动一个元素 |
next | 迭代器向后移动一个元素 |
示例
int main(int argc, char *argv[])
{
std::list<int32_t> ll_1{23,4,5,6,12};
auto iter_begin = ll_1.begin();
auto iter_end = ll_1.begin();
std::advance(iter_end, 3); //iter_end向后移动3个位置
std::cout<<"iter_begin is: "<<*iter_begin<<std::endl;
std::cout<<"iter_end is: "<<*iter_end<<std::endl;
auto dis = std::distance(iter_begin,iter_end); //计算iter_begin和iter_end之间的距离
std::cout<<"the distance is: "<<dis<<std::endl<<std::endl;
std::advance(iter_begin, 1);
std::cout<<"iter_begin value is: \t"<<*iter_begin<<std::endl;
std::cout<<"begin(iter_begin) value is: \t"<<*std::begin(ll_1)<<std::endl; //输出list的头元素
std::cout<<"end(iter_begin) value is: \t"<<*std::end(ll_1)<<std::endl; //输出list的尾元素
std::cout<<"prev(iter_begin) value is: \t"<<*(std::prev(iter_begin))<<std::endl; //向前移动一个元素
std::cout<<"next(iter_begin) value is: \t"<<*std::next(iter_begin)<<std::endl; //向后移动一个元素
return 0;
}
输出
iter_begin is: 23
iter_end is: 6
the distance is: 3
iter_begin value is: 4
begin(iter_begin) value is: 23
end(iter_begin) value is: 5
prev(iter_begin) value is: 23
next(iter_begin) value is: 5