【C++】list的介绍及使用说明

news2024/12/23 13:41:40

目录

00.引言

01.list的介绍

模版类

独立节点存储

list的使用

1.构造函数

2.迭代器的使用

分类

运用

3.容量管理

empty():

size():

4.元素访问

5.增删查改


00.引言

我们学习数据结构时,学过两个基本的数据结构:顺序表链表顺序表中的数据是连续存储的,并且支持随机访问,但是增删数据的效率比较低,因为要挪动数据;链表中的数据是分散存储的,每个节点包含一个数据和指向令一个节点的指针,不支持随机访问,但插入和删除操作的效率较高。

vector容器内部数据存储原理可以认为是顺序表,而list可以认为是双向链表(每个节点都包含指向前一个和后一个节点的指针)。

01.list的介绍

模版类

和"std::vector"一样,“std::list”实现不同类型数据的管理也是通过模版类的机制实现的。当创建一个list对象时,可以通过模版参数来指定存储的元素类型。使用"<数据类型>"来显式实例化指定存储的元素类型,例如“std::list<int>”表示存储整数类型的链表,“std::list<double>”表示存储双精度浮点型的链表……

#include <iostream>

template<typename T>
class list {
    ……
};

int main() {
    list<int> myList1;
    list<double> myList2;

    return 0;
}

独立节点存储

list的底层是双向链表结构,双向链表中每个元素存储在互不相关的独立节点中,在节点中通过指针指向其前一个元素和后一个元素。因此list可以在任意位置进行插入和删除,且时间复杂度为O(1),并且该容器可以前后双向迭代。

list的使用

在cpluscplus网站上有具体的list的使用说文档:list使用文档,在实际运用中,需要熟悉一些常用的list接口,以下列出了一些常见接口:

1.构造函数

在使用list创建对象之前,需要包含头文件“<vector>”。

我们需要调用构造函数来创建对象,list的构造函数有以下几种:

1.list():无参构造

2.list(size_type n,const value_type& val = value_type()):初始化n个val的元素

3.list(const list& x):拷贝构造函数

4.list(inputiterator first, inputiterator last):用(first,last)区间中的元素构造

代码演示:


void text1()
{
    list<int> l1;
    list<int> l2(5, 10);
    list<int> l3(l2);
    list<int> l4(l3.begin(), l3.end());

    int arr[] = { 0,1,2,3,4 };
    list<int> l5(arr, arr + 5);
}

运行结果:

2.迭代器的使用

可以将 list 中的迭代器理解为一个指针,该指针指向list中的某一个节点

分类

    · begin + end:返回第一个数据位置的迭代器 + 返回最后一个数据的下一个位置的迭代器

    · rbegin + rend:返回第一个元素的reverse_iterator,即end位置 + 返回最后一个元素下一个位置的reverse_iterator,即begin位置

注意:

1.begin与end为正向迭代器,对迭代器执行++操作,迭代器向后移动

2.rbegin(end)与rend(begin)为反向迭代器,对迭代器执行++操作,迭代器向前移动

运用

遍历list只能用迭代器和范围for,而vector还可以用类似与数组的下标[]访问,那是因为vector中的数据是连续存储的,而list中是分散存储的,元素地址直接并无关联。

迭代器和范围for遍历:


void text2(const list<int>& l)
{
    for (list<int>::const_iterator it = l.begin(); it != l.end(); ++it) {
        cout << *it << " ";
        //*it = 10; 编译不通过
    }
    cout << endl;
}
int main() {
    //text1();
    list<int> l{ 1,2,3,4,5,6,7,8,9 };
    text2(l);
    return 0;
}

运行结果: 

可以看到这里使用的是const迭代器,这表示迭代器指向的元素是不可被修改的,来看看const_iterator的底层是这样定义的:

class list {
public:
    // other members...

    // 内部定义 const_iterator
    typedef const T* const_iterator;
};

所以const迭代器指向的元素是常量,不可进行修改操作,而迭代器本身是可以++或--的,如果是

typedef T* const const_iterator;

这种方式定义,则表示迭代器本身不可++或--操作,其指向的元素则可以被修改。

正向反向迭代器:


void text3()
{
    int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
    list<int> l(array, array + sizeof(array) / sizeof(array[0]));
    // 使用正向迭代器正向list中的元素
    // list<int>::iterator it = l.begin();   // C++98中语法
    auto it = l.begin();                     // C++11之后推荐写法
    while (it != l.end())
    {
        cout << *it << " ";
        ++it;
    }
    cout << endl;

    // 使用反向迭代器逆向打印list中的元素
    // list<int>::reverse_iterator rit = l.rbegin();
    auto rit = l.rbegin();
    while (rit != l.rend())
    {
        cout << *rit << " ";
        ++rit;
    }
    cout << endl;
}

int main() {
    text3();
    return 0;
}

运行结果: 

在C++11中引入了auto关键字,编译器会自动推导auto定义的变量的类型,具体内容可以参考我的这篇博客:auto关键字与基于范围的for循环(C++11)

3.容量管理

list虽然不需要动态开辟管理内存空间,但是还是要对节点的数量(数据的个数)进行跟踪管理

empty():

用于检查列表是否为空。如果列表为空,则返回 ‘true’,否则返回 ‘false’。

代码演示:


void text4()
{
    list<int> myList;
    if (myList.empty()) {
        std::cout << "List is empty!" << std::endl;
    }
    else {
        std::cout << "List is not empty. Size: " << myList.size() << std::endl;
    }

}

int main() {
    text4();
    return 0;
}

 运行结果:

size():

用于获取列表中的数量。

代码演示:


void text5()
{
    list<int> myList = { 1, 2, 3, 4, 5 };
    std::cout << "Size of list: " << myList.size() << std::endl;
}

int main() {
    text5();
    return 0;
}

运行结果:

4.元素访问

有别与begin、end,list中可以通过front、back函数分别获取list的第一个节点的引用和最后一个节点的引用,是直接获取元素本身,而不是元素地址(指向元素的迭代器(指针))。

代码演示:

void text6()
{
    list<int> myList = { 1, 2, 3, 4, 5 };
    int firstElement = myList.front();
    cout << "First element: " << firstElement << endl;
    int lastElement = myList.back();
    cout << "Last element: " << lastElement << endl;

}

int main() {
    text6();
    return 0;
}

5.增删查改

下面是代码演示:


void PrintList(const list<int>& l)
{
    // 注意这里调用的是list的 begin() const,返回list的const_iterator对象
    for (list<int>::const_iterator it = l.begin(); it != l.end(); ++it)
    {
        cout << *it << " ";
        // *it = 10; 编译不通过
    }

    cout << endl;
}

// list插入和删除
// push_back/pop_back/push_front/pop_front
void Test1()
{
    int array[] = { 1, 2, 3 };
    list<int> L(array, array + sizeof(array) / sizeof(array[0]));

    // 在list的尾部插入4,头部插入0
    L.push_back(4);
    L.push_front(0);
    PrintList(L);

    // 删除list尾部节点和头部节点
    L.pop_back();
    L.pop_front();
    PrintList(L);
}

// insert /erase 
void Test2()
{
    int array1[] = { 1, 2, 3 };
    list<int> L(array1, array1 + sizeof(array1) / sizeof(array1[0]));

    // 获取链表中第二个节点
    auto pos = ++L.begin();
    cout << *pos << endl;

    // 在pos前插入值为4的元素
    L.insert(pos, 4);
    PrintList(L);

    // 在pos前插入5个值为5的元素
    L.insert(pos, 5, 5);
    PrintList(L);

    // 在pos前插入[v.begin(), v.end)区间中的元素
    vector<int> v{ 7, 8, 9 };
    L.insert(pos, v.begin(), v.end());
    PrintList(L);

    // 删除pos位置上的元素
    L.erase(pos);
    PrintList(L);

    // 删除list中[begin, end)区间中的元素,即删除list中的所有元素
    L.erase(L.begin(), L.end());
    PrintList(L);
}

// resize/swap/clear
void Test3()
{
    // 用数组来构造list
    int array1[] = { 1, 2, 3 };
    list<int> l1(array1, array1 + sizeof(array1) / sizeof(array1[0]));
    PrintList(l1);

    // 交换l1和l2中的元素
    list<int> l2;
    l1.swap(l2);
    PrintList(l1);
    PrintList(l2);

    // 将l2中的元素清空
    l2.clear();
    cout << l2.size() << endl;
}

int main() {
    Test1();
    Test2();
    Test3();
    return 0;
}

运行结果: 

以上就是关于list的介绍和使用说明的有关知识了,欢迎在评论区留言~感觉这篇博客对您有帮助的可以点赞关注支持一波喔~😉 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1606254.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于simulink的模拟锁相环和数字锁相环建模与对比仿真

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 4.1 模拟锁相环&#xff08;PLL&#xff09;的基本原理 4.2 数字锁相环&#xff08;DPLL&#xff09;的基本原理 5.完整工程文件 1.课题概述 模拟锁相环和数字锁相环建模的simulink建模&#xff0c;对…

深度剖析哈希

目录 一. 哈希概念 1.1 哈希概念 1.2 哈希冲突 1.3 哈希函数 二. 闭散列 2.1 线性探测法 2.2 引进状态 2.3 闭散列的查找、插入、删除操作 2.4 闭散列插入时的扩容 2.4 仿函数 2.5 整体代码 三. 开散列 ​编辑 2.1 闭散列节点定义 2…

HBuilder真机调试检测不到荣耀Magic UI系列(包括手机和电脑)解决办法

HBuilder真机调试检测不到荣耀Magic UI系列&#xff08;包括手机和电脑&#xff09;解决办法解决方法&#xff1a; 1.在开发人员选项中开启USB调试 如何进入开发者选项&#xff1f; 设置->关于->版本号&#xff0c;点击版本号直至出现您已处于开发者模式 2.选择USB配置…

Swin Transformer 浅析

Swin Transformer 浅析 文章目录 Swin Transformer 浅析引言Swin Transformer 的网络结构W-MSA 窗口多头注意力机制SW-MSA 滑动窗口多头注意力机制Patch Merging 图块合并 引言 因为ViT无法实现CNN中的层次化构建以及局部信息&#xff0c;由此微软团队提出了Swin Transformer来…

【论文阅读】YOLO-World | 开集目标检测

Date&#xff1a;2024.02.22&#xff0c;Tencent AI Lab&#xff0c;华中科技大学Paper&#xff1a;https://arxiv.org/pdf/2401.17270.pdfGithub&#xff1a;https://github.com/AILab-CVC/YOLO-World 论文解决的问题&#xff1a; 通过视觉语言建模和大规模数据集上的预训练来…

【QT+OpenCV】车牌号检测 学习记录 遇到的问题

【QTOpenCV】车牌号检测 学习记录 首先在QT里面配置好OpenCV .pro文件中加入&#xff1a; INCLUDEPATH G:/opencv/build/include LIBS -L"G:/opencv/build/x64/vc14/lib"\-lopencv_core \-lopencv_imgproc \-lopencv_highgui \-lopencv_ml \-lopencv_video \-lo.c…

展览展会媒体媒体邀约执行应该怎么做?

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好&#xff0c;我是51媒体网胡老师。 展览展会邀请媒体跟其他活动邀请媒体流程大致相同&#xff0c;包括 制定媒体邀约计划&#xff0c;准备新闻稿&#xff0c;发送邀请函&#xff0c;确认媒体参会&#xff0c;现场媒体接待及…

页缓存(PageCache)和预读机制(readahead )

页缓存&#xff08;PageCache)和预读机制&#xff08;readahead &#xff09; 页缓存&#xff08;PageCache)是操作系统&#xff08;OS&#xff09;对文件的缓存&#xff0c;用于加速对文件的读写。 page 是内存管理分配的基本单位&#xff0c; Page Cache 由多个 page 构成&…

【观察】容器化部署“再简化”,云原生体验“再升级”

自2013年云原生概念被提出以来&#xff0c;云原生技术和架构在过去十多年得到了迅速的发展&#xff0c;并对数字基础设施、应用架构和应用构建模式带来了深刻的变革。根据IDC预测&#xff0c;到2024年&#xff0c;新增的生产级云原生应用在新应用的占比将从2020年的10%增加到60…

YoloV9改进策略:下采样改进|自研下采样模块(独家改进)|疯狂涨点|附结构图

摘要 本文介绍我自研的下采样模块。本次改进的下采样模块是一种通用的改进方法&#xff0c;你可以用分类任务的主干网络中&#xff0c;也可以用在分割和超分的任务中。已经有粉丝用来改进ConvNext模型&#xff0c;取得了非常好的效果&#xff0c;配合一些其他的改进&#xff0…

MTK MFNR 学习笔记

和你一起终身学习&#xff0c;这里是程序员Android 经典好文推荐&#xff0c;通过阅读本文&#xff0c;您将收获以下知识点: 一、MFNR 简介二、MFNR 开关与决策三、MFNR 相关的adb 命令四、MFNR log 分析五 参考文献 一、MFNR 简介 MFNR : Multiple Frame Noise ReductionMFLL …

lv_micropython for ESP32/S2/S3/C3

由于官方的lv_micropython编译ESP32S3/S2/C3会报错&#xff0c;因为这些芯片的esp-idf底层重写了接口&#xff0c;参照网友提供的方法修改lv_bindings/driver/esp32里的文件&#xff0c;解决编译错误。 问题列举&#xff1a;Issues lvgl/lv_binding_micropython GitHub 一…

Maven的dependencyManagement与dependencies区别

先说结论&#xff1a;Maven 使用dependencyManagement 元素来提供了一种管理依赖版本号的方式。 在maven多模块项目的pom文件中&#xff0c;有的小伙伴会发现最外层的pom文件和里面的pom文件有个地方不一样 如下图 父pom 子pom 一般来说是在maven的最外父工程pom文件里&…

4.18学习总结

多线程补充 等待唤醒机制 现在有两条线程在运行&#xff0c;其中一条线程可以创造一个特殊的数据供另一条线程使用&#xff0c;但这个数据的创建也有要求&#xff1a;在同一时间只允许有一个这样的特殊数据&#xff0c;那么我们要怎样去完成呢&#xff1f;如果用普通的多线程…

云原生Kubernetes: K8S 1.29版本 部署Kuboard

目录 一、实验 1.环境 2.K8S 1.29版本 部署Kuboard (第一种方式) 3.K8S 1.29版本 部署Kuboard (第二种方式) 4.K8S 1.29版本 使用Kuboard 二、问题 1.docker如何在node节点间移动镜像 一、实验 1.环境 &#xff08;1&#xff09;主机 表1 主机 主机架构版本IP备注ma…

Java学习-Module的概念和使用、IDEA的常用设置及常用快捷键

Module的概念和使用 【1】在Eclipse中我们有Workspace (工作空间)和Project (工程)的概念&#xff0c;在IDEA中只有Project (工程)和Module (模块)的概念。 这里的对应关系为: IDEA官网说明: An Eclipse workspace is similar to a project in IntelliJ IDEA An Eclipse pr…

二刷大数据(三)- Flink1.17

目录 Flink概念与SparkStreaming区别分层API 工作流程部署模式**Local Mode****Standalone Mode****YARN Mode****Kubernetes Mode****Application Mode** 运行架构stand alone 核心概念算子链任务槽 窗口窗口**窗口的目的与作用****时间窗口&#xff08;Time Windows&#xff…

ARouter之kotlin build.gradle.kts

ARouter之kotlin build.gradle.kts kotlin的配置需要用到kapt 项目的build.gradle.kts plugins {id("com.android.application") version "8.1.2" apply falseid("org.jetbrains.kotlin.android") version "1.9.0" apply falseid(&…

typecho博客的相对地址实现

typecho其中的博客地址,必须写上绝对地址,否则在迁移网址的时候会出现问题,例如页面记载异常 修改其中的 typecho\var\Widget\Options\General.php 中的165行左右, /** 站点地址 */if (!defined(__TYPECHO_SITE_URL__)) {$siteUrl new Form\Element\Text(siteUrl,null,$this-…

OpenCV从入门到精通实战(五)——dnn加载深度学习模型

从指定路径读取图像文件、利用OpenCV进行图像处理&#xff0c;以及使用Caffe框架进行深度学习预测的过程。 下面是程序的主要步骤和对应的实现代码总结&#xff1a; 1. 导入必要的工具包和模型 程序开始先导入需要的库os、numpy、cv2&#xff0c;同时导入utils_paths模块&…