C++ STL容器—— list 成员函数用法详解
写在前面:近期正在重新学习C++的STL容器,因此准备将STL函数的用法详细记录一下,主要介绍一些基本成员函数的用法, 外加实际的例子,并不涉及原理。其实了解这些函数最好的方法还是需要自己上手操作一下.
写的不好, 请大神手下留情.
下面说的 “运行之后” 表示: 运行上个语句之后的结果.
一行如果说的太长的话, 就得拖动下面的进度条才能看到后面的内容, 非常麻烦
因此将一段话分成了多行,就像现在这种形式
简介
需要头文件:# include < list >
动态双向链表, 不过一些成员函数的基本用法和 vector 相同, 点击前往: vector 成员函数用法详解
构造函数
list <int> l, l1;
//定义 int 类型的数组
list <char> lch;
//定义 char 类型的数组
list <string> lstr;
//定义 string 类型的数组
list <int> l2(10);
//定义拥有 10 个空间的数组, 不说的话这 10 个元素都是 0
list <int> l3(5, 30);
//定义拥有 5 个空间的数组,并全部初始化为 30
list <int> l4 = { 1,2,3,4 };
//定义拥有 4 个空间的数组, 初始化为{1,2,3,4}
list <int> l5{ 1,2,3,4 };
//同上
list <int> l6(l);
//定义一个和 l 容器具有相同元素的容器 l1
list <int> l7(l3.begin(), l3.begin());
//定义容器 l7, 并赋值 l3 范围内的元素
不能使用下标 [] 随机访问
迭代器
包括: begin、end、rbegin、end、cbegin、cend、crbegin、crend
使用方法:
auto it=l.begin(); //相当于指针,用 *it 访问
l.begin(); //返回指向l第一个元素的迭代器
l.end(); //返回指向l最后一个元素下一个元素的迭代器
l.rbegin(); //返回指向逆序第一个元素的迭代器
l.cbegin(); //返回指向l第一个元素的迭代器, 类型为const
l.crbegin(); //返回指向逆序第一个元素的迭代器, 类型为const
例: 使用正向遍历 l 数组
list <int> l{ 1,2,3,4,5,6 };
for (auto it = l.begin(); it != l.end(); it++) {
//注意这里是不等于end, 而不是小于end
cout << *it <<' ';
}
输出结果为:
1 2 3 4 5 6
例: 反向遍历 l 数组
list <int> l{ 1,2,3,4,5,6 };
for(auto it=l.rbegin();it!=l.rend();it++){
//注意这里还是it++, 而不是it--
cout << *it <<' ';
}
输出结果为:
6 5 4 3 2 1
begin和rbegin的区别
l.begin() 返回迭代器,指向 l 第一个元素
l.rbegin() 返回逆序迭代器,指向 l 最后一个元素
遍历
l.begin(),l.begin()+1,···,l.end()-1,l.end()
l.rbegin(),l.rbegin()+1,···,l.rend()-1,l.rend()
begin和cbegin的区别
可以通过l.begin()修改 l 的值 (具体可不可以需要看 l )
不能通过l.cbegin()修改 l 的值
常用函数
l.push_front(4);
//在头部插入元素 4, vector 没有这个函数
//例:l={1,2,3}
//运行之后, l={4,1,2,3}
l.push_back(4);
//在 l 末尾添加元素 4
//例:l={1,2,3}
//运行之后, l={1,2,3,4}
l.pop_front();
//删除第一个元素, vector 没有这个函数
//例:l={1,2,3,4}
//运行之后, l={2,3,4}
l.pop_back();
//删除 l 最后一个字符
//例:l={1,2,3,4}
//运行之后, l={1,2,3}
l.front();
//返回 l 的第一个元素
//例:l={1,2,3,4}
//l.front()就等于 1
l.back();
//返回 l 的最后一个元素
//例:l={1,2,3,4}
//l.back()就等于 4
l.clear();
//清空 l 容器
l.empty();
//返回 l 容器是否为空, 空的返回 true, 非空返回 false
l.swap(l1);
//将 l 与 l1 交换
//例:l={1,2,3,4}, l1={5,6,7}
//运行之后, l={5,6,7}, l1={1,2,3,4}
l.reverse();
//将容器的所有元素进行翻转
//例:l={1,2,3,4}
//运行之后, l={4,3,2,1}
assign(赋值函数)
l.assign(2, 3);
//将 2 个 3 赋值给 l
//例:l={5,6,7}
//运行之后 l={3,3,3}
l.assign(l1.begin(), l1.end());
//将迭代器指向的内容赋值给 l
//例:l={5,6,7}, l1={1,2,3,4}
//运行之后 l={1,2,3,4}
长度函数
l.size();
//返回容器元素的个数
//例: l={1,2,3}
//返回 3
l.max_size();
//返回 l 最多能保存元素的个数
//返回一个数字, 根据编译环境的不同, 这个数字也不同.
l.resize(3);
//设置 l 的 size,影响 size
//设置之后 size=3
//例:l={1,2,3,4,5,6}
//运行之后 l={1,2,3}, 如果尺寸变小,多余的部分截掉
//例:l={1,2}
//运行之后 l={1,2,0}, 如果尺寸变大,新空间用 0 代替
l.resize(3, 2);
//设置 l 的 size,如果尺寸变大,新空间全部用 2 代替
//例: l={1,1}
//运行之后 l={1,1,2}
insert(插入函数)
返回指向插入位置的迭代器(即: 第一个参数)
l.insert(l.begin(), 3);
//在位置上插入元素 3
//例: l={1,2}
//运行之后 l={3,1,2}
l.insert(l.begin(), 2, 3);
//在位置上插入 2 个元素 3
//例: l={1,2}
//运行之后 l={3,3,1,2}
l.insert(l.begin(), l1.begin(), l1.end());
//在位置上插入指向 l1 范围的元素
//例: l={1,2}, l1={5,6,7},
//运行之后 l={5,6,7,1,2}
erase(删除函数)
返回指向删除位置的迭代器(即: 第一个参数)
l.erase(l.begin());
//删除位置上的元素
//例: l={1,2,3}
//运行之后 l={2,3}
l.erase(l.begin(), l.end());
//删除范围内的元素
//例: l={1,2,3}
//运行之后 l={}
emplace系列(插入函数)
返回指向插入位置的迭代器
l.emplace(l.begin(), 3);
//在位置上插入元素 3, 相当于l.insert(l.begin(),3);
//例: l={1,2,4}
//运行之后 l={3,1,2,4}
l.emplace_front(3);
//在开头插入元素 3, 相当于l.push_front(3);
//例: l={1,2}
//运行之后 l={3,1,2}
l.emplace_back(3);
//在最后插入元素 3, 相当于l.push_back(3);
//例: l={1,2}
//运行之后 l={1,2,3}
emplace与push_back/insert的区别
- 原理上
emplace是直接将插入的内容放进容器里面, 不需要生成对象
push_back/insert是先生成对象, 然后将对象的内容复制到容器里面 - 功能上
emplace只能插入一个元素
push_back/insert可以插入多个 - 性能上
emplace的速度要更快一点
push_back与insert的区别
- 功能上
push_back只能在最后添加元素
insert可以在任何地方添加元素 - 性能上
push_back速度要更快一点
merge(合并函数)
将参数指向的内容移动到本容器里面, 元素必须有序
l.merge(l1);
//将 l1 的内容合并到 l 里
l 和 l1 的元素必须是升序排列, 执行之后 l1 清空, l 里的元素按升序排列
例: l={1,3,5}, l1={2,4,6}
执行之后, l={1,2,3,4,5,6}, l1={};
l.merge(l1, greater <int>());
//将 l1 的内容合并到 l 里
l 和 l1 的元素必须是降序排列, 执行之后 l1 清空, l 里的元素按降序排列
例: l={5,3,1}, l1={6,4,2}
执行之后, l={6,5,4,3,2,1}, l1={};
l.merge(l1, cmp);
//按照自定义的 cmp 合并之后排序
splice(拼接函数)
执行之后,删除 l1 插入的元素
l.splice(l.begin(), l1);
//将 l1 所有元素插入到 l 迭代器指向的位置
//例: l={1,2}, l1={5,6,7},
//运行之后 l={5,6,7,1,2}, l1={};
l.splice(l.begin(), l1, l1.begin());
//将 l1 迭代器指向的元素移动并插入到 l 迭代器指向的位置
//例: l={1,3,5}, l1={2,4,6}
//执行之后, l={2,1,3,5}, l1={4,6};
l.splice(l.begin(), l1, l1.begin(), l1.end());
//将 l1 迭代器指向的内容移动并插入到 l 迭代器指向的位置
//例: l={1,2}, l1={5,6,7},
//运行之后 l={5,6,7,1,2}, l1={};
insert / merge / splice 三个插入函数的区别
a.函数名(b)
将容器 b 的内容插入到容器 a 中
insert 函数就是正常的将容器 b 的内容复制插入到容器 a 中
merge 函数在使用之前两个容器必须具有相同的顺序(升序/降序/自定义的顺序), 是将容器 b 的内容按照一定的顺序移动插入到容器 a 中, 会将容器 b 中插入的内容删除
splice 函数是将容器 b 的内容移动插入到容器 a 中, 会将容器 b 中插入的内容删除
remove系列(移除函数)
查找值之后删除
l.remove(3);
//将容器里所有值为 3 的元素删除
//例: l={1,2,3,3,4,3,3}
//运行之后 l={1,2,4}
l.remove_if(cmp);//将符合 cmp 条件的元素删除
bool cmp(int a) {
// 10~100 返回 false, 其余返回 true
//其实就是删除10~100之外的数
return a < 10 || a>100;
}
//例: l={1,2,10,50,60,100,111}
//运行之后 l={10,50,60,100}
unique(排重函数)
l.unique();
//删除容器中相邻的相同元素(会留一个)
//例: l={1,2,3,3,3,4,5,5,6}
//运行之后 l={1,2,3,4,5,6}
erase / remove / unique 三个删除函数的区别
erase 函数是通过迭代器查找到元素之后, 进行删除
remove 函数是通过 值 查到元素之后, 进行删除
unique 函数只将相邻的相同元素删除, 达到排重的效果
sort(排序函数)
l.sort();
//升序排序
//例: l={1,2,3,5,4,1,3}
//运行之后 l={1,1,2,3,3,4,5}
l.sort(greater<int>());
//降序排序
//例: l={1,2,3,5,4,1,3}
//运行之后 l={5,4,3,3,2,1,1}
l.sort(cmp);
//自定义排序依据 cmp
sort 和 unique 函数结合
正常来说是不会用到 unique 函数的, 他一般和 sort 函数配套使用, 达到将容器中相同的多余元素删除的效果(真正意义上的排重)
例如:
l={2,5,1,6,1,3,2,4,1,5,6};
直接执行 unique 函数是不能真正做到排重的
只有先进行 sort 排序, 再执行 unique 函数, 才能达到要求
l.sort();
l.unique();
执行之后, l={1,2,3,4,5,6}
写在最后:
cmp 是自定义的操作依据, 毕竟C++不可能把所有情况都内置在函数里, 要想实现比较复杂的操作依据只能自己写个 cmp 函数
cmp 的这个名字是大家都这个用, 也可以自己设定.
本人只会最简单的使用cmp, 因此在文章中并没有进行详细介绍.
转载:https://blog.csdn.net/wzh1378008099/article/details/105770504