C++ 11 STL list

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;
}

插入和删除不会使迭代器失效。 删除建议使用remove/remove_if

相关推荐
数据小爬虫@9 分钟前
如何高效利用Python爬虫按关键字搜索苏宁商品
开发语言·爬虫·python
ZJ_.11 分钟前
WPSJS:让 WPS 办公与 JavaScript 完美联动
开发语言·前端·javascript·vscode·ecmascript·wps
Narutolxy16 分钟前
深入探讨 Go 中的高级表单验证与翻译:Gin 与 Validator 的实践之道20241223
开发语言·golang·gin
Hello.Reader24 分钟前
全面解析 Golang Gin 框架
开发语言·golang·gin
禁默35 分钟前
深入浅出:AWT的基本组件及其应用
java·开发语言·界面编程
yuyanjingtao37 分钟前
CCF-GESP 等级考试 2023年9月认证C++四级真题解析
c++·青少年编程·gesp·csp-j/s·编程等级考试
Code哈哈笑44 分钟前
【Java 学习】深度剖析Java多态:从向上转型到向下转型,解锁动态绑定的奥秘,让代码更优雅灵活
java·开发语言·学习
程序猿进阶1 小时前
深入解析 Spring WebFlux:原理与应用
java·开发语言·后端·spring·面试·架构·springboot
qq_433618441 小时前
shell 编程(二)
开发语言·bash·shell
闻缺陷则喜何志丹1 小时前
【C++动态规划 图论】3243. 新增道路查询后的最短距离 I|1567
c++·算法·动态规划·力扣·图论·最短路·路径