C++容器——双向链表(list)

文章介绍了C++标准库中的list容器,它是一种基于双向链表的数据结构,支持在任何位置插入和删除元素,但不支持随机访问。内容涵盖了list的初始化、元素的访问、大小管理、元素修改、操作以及迭代器的使用,提供了丰富的示例代码来展示其功能和用法。
摘要由CSDN通过智能技术生成

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
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值