- list
- [list 比较](#list 比较)
- 插入
- 删除
- remove删除元素
- [list 特有](#list 特有)
- 排序
- [对象排序 和 取反not2](#对象排序 和 取反not2)
- unique删除重复元素
- 拼接相关操作
- 不支持随机访问
- 高效的插入和删除
- [插入和删除不会使迭代器失效。 删除建议使用remove/remove_if](#插入和删除不会使迭代器失效。 删除建议使用remove/remove_if)
list
list是C++标准模板库(STL)中的一个容器,用于存储元素的双向链表。它提供了高效的插入和删除操作,但在随机访问方面不如vector高效。
c++
//todo list
# include <iostream>
#include <list>
using namespace std;
void print(list<int> & li){
//使用迭代器遍历list
for(list<int>::iterator it=li.begin();it!=li.end();it++){
cout<<*it<<" ";
}
cout<<endl;
}
int main() {
list<int> li={1,2,3,4,5};
cout<<li.front()<<endl;//1
cout<<li.back()<<endl;//5
print(li);
li.push_back(6);//添加元素
print(li); //1 2 3 4 5 6
li.pop_back();//删除最后一个元素
print(li); //1 2 3 4 5
li.pop_front();//删除第一个元素
print(li);//2 3 4 5
li.sort();//排序
print(li);//2 3 4 5
li.reverse();//反转
print(li);//5 4 3 2
li.remove(3);//删除所有值为3的元素
print(li);//2 4 5
li.unique();//删除重复元素
print(li);//2 4 5
li.resize(1);//调整大小
print(li);//2
li.clear();//清空list
print(li);
li.insert(li.begin(),10);//在第一个位置插入元素
print(li);//10
li.erase(li.begin());//删除第一个元素
print(li);//10
return 0;
}
c++
# if 1
//todo list
#include <iostream>
#include <list>
using namespace std;
void print(list<int> & li){
list<int> ::iterator it ;
for (it=li.begin();it!=li.end();++it){
cout<<*it<<" ";
}
cout<<endl;
}
int main(){
int arr[10]={1,2,3,4};
list<int> li(arr,arr+4);
list<int> li2(li.begin(),li.end());
print(li);
print(li2);
cout<<li2.size()<<endl;//4
while (!li2.empty()){
cout<<li2.back();
li2.pop_back();
}
cout<<li2.size()<<endl;//0
return 0;
}
# endif
list 比较
比较对象要重载==和!=运算符
c++
int main(){
//比较基本数据类型
list<int> li1={1,2,3,4};
list<int> li2={1,2,3,4};
if(li1==li2){
cout<<"=="<<endl;
} else{
cout<<"!="<<endl;
}
//比较对象要重载==和!=运算符
return 0;
}
插入
c++
#include <iostream>
#include <list>
#include <iterator>
using namespace std;
void print(list<int> & li){
//for(auto it=li.begin();it!=li.end();++it){ cout<<*it<<" "; }
for(list<int>::iterator it =li.begin();it!=li.end();++it){
cout<<*it<<" ";
}
cout<<endl;
}
int main(){
list<int> li={1,2,3,4,5};
li.insert(li.begin(),333);//开头插入333
print(li);//333 1 2 3 4 5
li.insert(li.end(),2,666);//末尾插入2个666
print(li);//333 1 2 3 4 5 666 666
int arr[]={6,7,8};
li.insert(li.end(),arr,arr+3);//插入一个范围
print(li);//333 1 2 3 4 5 666 666 6 7 8
li.insert(li.end(),{77,77,77});//插入一个范围
print(li);//333 1 2 3 4 5 666 666 6 7 8 77 77 77
li.emplace(li.begin(),111);//在开头插入111
print(li);//111 333 1 2 3 4 5 666 666 6 7 8 77 77 77
li.emplace_back(222);//在末尾插入222
print(li);//111 333 1 2 3 4 5 666 666 6 7 8 77 77 77 222
li.emplace_front(333);//在开头插入333
print(li);//333 111 333 1 2 3 4 5 666 666 6 7 8 77 77 77 222
return 0;
}
删除
erase删除元素
c++
#include <iostream>
#include <list>
#include <iterator>
using namespace std;
void print(list<int> & li){
//for(auto it=li.begin();it!=li.end();++it){ cout<<*it<<" "; }
for(list<int>::iterator it =li.begin();it!=li.end();++it){
cout<<*it<<" ";
}
cout<<endl;
}
int main(){
list<int> li={1,2,3,4,5};
li.erase(li.begin());//删除第一个元素
print(li);//2 3 4 5
//list并非线性,所以不能+1
//li.erase(li.begin()+1);
list<int>::iterator it=li.begin();//获取迭代器
advance(it,1);//移动到第二个元素
li.erase(it);//删除第二个元素
print(li);//2 4 5
//支持 ++ -- 前缀和后缀运算符
li.erase(++li.begin());//删除第二个元素
print(li);//2 5
//删除范围
li.erase(li.begin(),li.end());//删除所有元素
print(li);//(空)
return 0;
}
remove删除元素
c++
//todo remove删除元素
#include <iostream>
#include <list>
#include <iterator>
using namespace std;
void print(list<int> & li){
//for(auto it=li.begin();it!=li.end();++it){ cout<<*it<<" "; }
for(list<int>::iterator it =li.begin();it!=li.end();++it){
cout<<*it<<" ";
}
cout<<endl;
}
int main(){
list<int> li={1,2,3,4,5};
li.remove(3);//删除所有值为3的元素
print(li);//1 2 4 5
cout<<li.size()<<endl;//4
//删除>=3的元素
li.remove_if([](int x){
if(x>=3)return true;
else return false;
});//返回值是bool的函数
print(li);//1 2
cout<<li.size()<<endl;//2
return 0;
}
list 特有
排序
基本类型
c++
//todo list排序
#include <iostream>
#include <list>
#include <iterator>
using namespace std;
void print(list<int> & li){
//for(auto it=li.begin();it!=li.end();++it){ cout<<*it<<" "; }
for(list<int>::iterator it =li.begin();it!=li.end();++it){
cout<<*it<<" ";
}
cout<<endl;
}
int main(){
list<int> li={5,3,1,4,2};
li.sort(less<int>());
li.sort();//默认less<int>()
print(li);//1 2 3 4 5
li.sort(greater<int>());
print(li);//5 4 3 2 1
//greater_equal是greater的升级版,即>=
li.sort(greater_equal<int>());
//less_equal是less的升级版,即<=
li.sort(less_equal<int>());
return 0;
}
对象排序 和 取反not2
c++
//todo 排序对象
#include <iostream>
#include <list>
using namespace std;
class A
{
public:
A()
{
cout<<"无参构造函数"<<this<<endl;
}
A(int i):_data(i)
{
cout<<"有参构造函数"<<this<<endl;
}
A(const A & other)
{
this->_data=other._data;
cout<<"拷贝构造"<<this<<" from "<<&other<<endl;
}
A& operator=(const A & other)
{
this->_data=other._data;
cout<<"拷贝赋值"<<this<<" from "<<&other<<endl;
return *this;
}
~A()
{
cout<<"析构函数"<<this<<endl;
}
//重载<运算符
bool operator<(const A & other) const
{
return _data<other._data;
}
void print(){
cout<<_data<<" ";
}
private:
int _data;
};
int main(){
list<A> li={A(3),A(2),A(1)};
li.sort(less<A>());//需要重载<运算符
for (auto & it:li){
it.print();
cout<<endl; // 1 2 3
}
//使用not1单参数的时候取反
//使用not2两个参数的时候取反
li.sort(not2(less<A>()));//取反
for (auto & it:li){
it.print();
cout<<endl; // 3 2 1
}
return 0;
}
unique删除重复元素
c++
//todo unique删除重复元素
#include <iostream>
#include <list>
using namespace std;
int main(){
list<int> li={1,2,3,3,4,5,5,4,3,2,1};
//li.unique();//去除了连续的重复元素
for (auto & it:li){
cout<<it<<" "; //1 2 3 4 5 4 3 2 1
}
cout<<endl;
li.sort();//先排序
li.unique();//再去重
for (auto & it:li){
cout<<it<<" "; //1 2 3 4 5
}
cout<<endl;
//自定义比较函数
li.unique([](int a,int b){
if(a==b ){
return true;
}else{
return false;
}
});
return 0;
}
拼接相关操作
c++
//todo 拼接相关操作
# include <iostream>
# include <list>
using namespace std;
void print(list<int> & li){
for(auto it=li.begin();it!=li.end();++it){
cout<<*it<<" ";
}
cout<<endl;
}
int main(){
list<int> li1={1,2,3,4,5};
list<int> li2={6,7,8,9,10};
//li1.splice(li1.begin(),li2);//拼接到末尾
//print(li1);//6 7 8 9 10 1 2 3 4 5
//print(li2);//拼接时发生移动,li2移动到li1,li2为空
// li1.splice(li1.end(),li2,li2.begin());
// print(li1);//1 2 3 4 5 6
// print(li2);//7 8 9 10
// auto itr=li1.begin();
// advance(itr,3);//移动到第四个元素
// li1.splice(itr,li2,li2.begin(),li2.end());
// print(li1);//1 2 3 6 7 8 9 10 4 5
list<int> li3={100,244,37,4,5};
list<int> li4={61,7,5558,97,10};
//需要merge有序需要先排序再merge
li3.merge(li4);//61 7 100 244 37 4 5 5558 97 10
print(li3);//1 2 3 4 5 6 7 8 9 10
print(li4);//空
}
c++
#include <list>
#include <iostream>
#include <algorithm>
#include <iterator>
using namespace std;
// 打印两个list的内容
void printLists(const list<int>& l1, const list<int>& l2)
{
cout << "list1: ";
// 使用copy算法和ostream_iterator将list1的内容输出到cout
copy(l1.cbegin(), l1.cend(), ostream_iterator<int>(cout, " "));
cout << endl << "list2: ";
// 使用copy算法和ostream_iterator将list2的内容输出到cout
copy(l2.cbegin(), l2.cend(), ostream_iterator<int>(cout, " "));
cout << endl << endl;
}
int main()
{
// 创建两个list对象
list<int> list1, list2;
// 向list1和list2中添加元素
for (int i = 0; i < 6; ++i)
{
list1.push_back(i); // 在list1的末尾添加元素
list2.push_front(i); // 在list2的头部添加元素
}
// 打印list1和list2的内容
printLists(list1, list2);
// 在list2中找到值为3的元素,并将list1的所有元素移动到该位置之前
list2.splice(find(list2.begin(), list2.end(), 3), list1);
// 打印list1和list2的内容
printLists(list1, list2);
// 将list2的第一个元素移动到list2的末尾
list2.splice(list2.end(), list2, list2.begin());
// 对list2进行排序
list2.sort();
// 将list2的内容赋值给list1
list1 = list2;
// 移除list2中的重复元素
list2.unique();
// 打印list1和list2的内容
printLists(list1, list2);
// 将list2合并到list1中
list1.merge(list2);
// 打印list1和list2的内容
printLists(list1, list2);
return 0;
}
不支持随机访问
list 容器由于采用了双向迭代器,不支持随机访问,所以标准库的 merge(),
sort()等功能函数都不适用,list 单独实现了 merge(),sort()等函数。
c++
#include <iostream>
#include <list>
#include <iterator>
#include <algorithm>
using namespace std;
int main()
{
// 创建一个list对象li,并初始化其内容为{1, 3, 5, 7, 9, 2, 4, 6, 8, 10}
list<int> li = {1, 3, 5, 7, 9, 2, 4, 6, 8, 10};
// 对li进行排序
li.sort();
// 遍历并输出排序后的li
for (auto &i : li)
cout << i << endl;
// 创建另一个list对象li2,并初始化其内容为{11, 12, 15, 13, 14}
list<int> li2 = {11, 12, 15, 13, 14};
// 将li2合并到li中
li.merge(li2);
// 对合并后的li进行排序
li.sort();
// 遍历并输出排序后的li
for (auto &i : li)
cout << i << "\t";
cout << endl;
// 遍历并输出li2的内容
for (auto &i : li2)
cout << i << "\t";
cout << endl;
return 0;
}
高效的插入和删除
插入和删除是高效的,元素不需移动,内存仅是指针移动
c++
#include <iostream>
#include <list>
#include <iterator>
#include <algorithm>
using namespace std;
// 定义类A
class A
{
public:
// 无参构造函数
A()
{
cout << "无参构造函数 " << this << endl;
}
// 有参构造函数
A(int i) : _data(i)
{
cout << "有参构造函数 " << this << endl;
}
// 拷贝构造函数
A(const A & other)
{
cout << "拷贝构造 " << this << " from " << &other << endl;
}
// 拷贝赋值运算符
A& operator=(const A & other)
{
cout << "拷贝赋值 " << this << " from " << &other << endl;
return *this;
}
// 析构函数
~A()
{
cout << "析构函数 " << this << endl;
}
private:
int _data; // 私有成员变量
};
int main()
{
// 创建一个存储A类型对象的list
list<A> la;
// 使用assign方法将list填充为10个临时A对象
la.assign(10, A());
// 删除list的第一个元素
la.erase(la.begin());
// 在list的开始位置插入一个新的临时A对象
la.insert(la.begin(), A());
return 0;
}