C++ | 四、指针、链表

指针

  • 指针用来储存地址
  • 定义方式,int *ptr;,使用*来表示所定义的变量是指针
  • 取地址符,ptr = &a;,通过&来取得一个普通变量的地址,并储存到指针中
  • 取值(解引用),想要取得一个指针变量所指向地址里储存的值,也是使用符号*,如b = *ptr即会把指针变量ptr存储地址里对应的值赋给b
  • 指针和数组的关系,实际上,数据结构就是基于指针设计的,例如数组int arr[2] = {1, 2};,其数组名arr实际上是一个存储了数组第一个元素地址的指针,比如可以使用int *ptr = arr;来把数组首元素的地址赋值给ptr
  • 指针的加减,指针可以通过加减来读取当前地址的相邻地址,并在使用取值符*(解引用)后可以读取相邻地址里的值,如int data = *(ptr + 2);
  • 空地址,C++中,使用一个特殊的字符nullptr用来表示当前指针不指向任何有效的内存地址,如int *ptr = nullptr;

链表基础知识

  • C++中为什么要使用链表结构
    • 可以充分利用小块的内存空间:因为诸如数组等数据结构,其必须占据一片连续的内存空间,此时如果数据量较大,则一些小内存空间就无法被利用,造成空间浪费;链表在内存中不连续储存,因此可以充分利用内存空间,具体见后面关于链表存储方式的介绍
    • 大小可变:数组不可变大小,因此不够灵活,而链表可以方便的进行增删等操作
    • 增删元素效率高:其它很多数据结构中,以增加元素为例,在增加之后,需要把后续所有元素都进行挪位,此时将严重影响效率,如图;而链表就没有这个问题,只需要改变所增加节点和其前一个节点,就可以完成增加元素的操作
    • 然而,链表也有缺点,就是查询效率低。这是因为链表中想要得到某一个节点的值,那就必须从前序节点依次寻址知道找到该节点
      • 其它数据结构增删效率低
  • 链表的结构:链表由多个节点组成,每个节点包括数据域data和指针域next,分别存储当前节点的数据和下一节点的地址
    • 链表的结构
    • 链表的第一个节点称为头节点head,在C++中,为了简化链表的插入和删除元素操作,通常在头节点前添加一个虚拟头节点dummyNode(可以不添加该虚拟头节点),该虚拟节点的data可以为空,但是next指针指向头节点的地址
    • 最后一个节点的next为nullptr
  • 链表的不同类型
    • 单链表,前面所提到的就是单链表,即单向链表,每个节点只存储下一节点的地址
    • 双链表,即双向链表,每个节点除了next指向下一节点外,还有prev指向上一节点,因此可以双向查询
      • 双链表
    • 循环链表,即头尾相接,也就是最后一个节点的next存储了头节点的地址(这种链表可以用来解决约瑟夫环的问题)
      • 循环链表
  • 链表的存储方式
    • 链表中的各个节点通过指针互相关联,因此不需要连续存储,具体的分配机制依不同的操作系统的内存管理机制而定
      • 链表的存储方式

链表节点结构体(struct)的自定义

  • 结构体struct可以用来自定义用户想要的数据类型,其地位等价于int、float、double这些数据类型(下面有一个结构体示例ListNode)
    • 结构体可以组合多种数据类型,如整型、浮点型、其它结构体等等
    • 定义一个结构体即一种新的数据类型之后,就可以使用该数据类型定义变量了
    • 定义的时候有多种初始化方式,常见的一种是使用构造函数。构造函数也是一种函数,但是它没有返回类型和返回值,另外它和结构体的名称相同,例如对于下面定义的这个ListNode结构体,其构造函数可以写为ListNode(int x) : val(x), next(nullptr) {},这里int x是形参,: val(x), next(nullptr)是一种初始化写法,冒号表示初始化列表的开始,后面表示val被赋值为x,next被赋值为nullptr
struct ListNode {int val;ListNode *next;ListNode(int x) : val(x), next(nullptr) {}  // 节点结构的构造函数
};

链表的操作

  • 删除节点
    • 将所删除节点上一节点的next指向所删除节点的下一节点即可
    • 在C++中,由于内存需要自己管理,因此最好把所删除节点的内存手动释放掉
    • 删除节点
  • 添加节点
    • 只要把所添加节点位置的上一节点指向所添加节点,再把所添加节点的next指向下一节点即可
    • 添加节点

时间复杂度性能分析

  • 可以看到,上面添加和删除节点操作本身的时间复杂度为O(1),但是要找到对应的节点位置(即查询)的时间复杂度为O(n),因此链表适用于需要频繁增删但是较少查询的场景
  • 性能对比
  • 有关时间复杂度更具体的介绍见我的另一篇文章

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

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

相关文章

【华为OD机试真题2023CD卷 JAVAJS】查找一个有向网络的头节点和尾节点

华为OD2023(C&D卷)机试题库全覆盖,刷题指南点这里 查找一个有向网络的头节点和尾节点 知识点图DFS搜索 时间限制:1s 空间限制:256MB 限定语言:不限 题目描述: 给定一个有向图,图中可能包含有环,图使用二维矩阵表示,每一行的第一列表示起始节点,第二列表示终止节…

Java 线程

1. 实现多线程的 2 种方式 Oracle 官网的文档中给出了 2 种实现多线程的方式: 实现 Runnable 接口;继承 Thread 类。 以上两种方式都会调用 Thread.run() 方法,区别是: 实现 Runnable 接口,只是执行 Thread.run() …

【新】Unity Meta Quest MR 开发(一):Passthrough 透视配置

文章目录 📕教程说明📕配置透视的串流调试功能📕第一步:设置 OVRManager📕第二步:添加 OVRPassthroughLayer 脚本📕第三步:在场景中添加虚拟物体📕第四步:设置…

202406读书笔记|《沉睡的线条世界》——翻山越岭,只为与你分享点滴的快乐

《沉睡的线条世界》登登登Dn绘著,简简单单的小画,简简单单的线条,简简单单的语言,温馨又有一点暖心。 怎样的你都好,做最真实的自己。 部分节选如下: 愿你我永远有热情,永远能为生活的每一个小惊…

阳光抑郁症测试

大部分人对抑郁症的理解,就是每天无精打采,死气沉沉,可实际上,还有一种阳光抑郁症,完全不是这个样子。这种抑郁症的人,做事情非常有活力,魅力十足,给人感觉十分有自信,但…

快速排序【hoare版本】【挖坑法】【双指针法】(数据结构)

快速排序是Hoare于1962年提出的一种二叉树结构的交换排序方法,其基本思想为:任取待排序元素序列中 的某元素作为基准值,按照该排序码将待排序集合分割成两子序列,左子序列中所有元素均小于基准值,右子序列中所有元素均…

MySQL多表查询(改进版)

1.创建student和score表 mysql> CREATE TABLE student (-> id INT(10) NOT NULL UNIQUE PRIMARY KEY ,-> name VARCHAR(20) NOT NULL ,-> sex VARCHAR(4) ,-> birth YEAR,-> department VARCHAR(20) ,-> address VARCHAR(50)-> ); Query O…

SpringCloud Nacos服务注册中心和配置中心

一、什么是Nacos? 官方介绍是这样的: Nacos 致力于帮助您发现、配置和管理微服务。Nacos 提供了一组简单易用的特性集,帮助您实现动态服务发现、服务配置管理、服务及流量管理。 Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。 Na…

Linux中放大字体

环境:VMware17Pro,Ubuntu22.04 在显示设置外观中只看到图标放大的调整,没看到字体大小设置 不按照常规设置,点开下面的辅助功能->大号文本(没有设置具体字号的选项,但是可以放大) 效果图如下…

day-10 删除排序链表中的重复元素

思路 先统计每个值出现的次数,然后将出现次数为一的节点链接为一个链表即可 解题方法 while(t!null){ //统计每个值出现次数 arr[t.val100]1; tt.next; } while(t!null&&arr[t.val100]!1) tt.next;//确定返回的头结点 ttt; while(t!null&&t.next…

项目解决方案:多个分厂的视频监控汇聚到总厂

目 录 1、概述 2、建设目标及需求 2.1 建设目标 2.2 需求描述 2.3 需求分析 3. 设计依据与设计原则 3.1 设计依据 3.2设计原则 1、先进性与适用性 2、经济性与实用性 3、可靠性与安全性 4、开放性 5、可扩充性 6、追求最优化的系统设备配置…

Zynq7020 使用 Video Processing Subsystem 实现图像缩放

1、前言 没玩过图像缩放都不好意思说自己玩儿过FPGA,这是CSDN某大佬说过的一句话,鄙人深信不疑。。。 目前市面上主流的FPGA图像缩放方案如下:1:Xilinx的HLS方案,该方案简单,易于实现,但只能用…

java+vue基于Spring Boot的渔船出海及海货统计系统

该渔船出海及海货统计系统采用B/S架构、前后端分离进行设计,并采用java语言以及springboot框架进行开发。该系统主要设计并完成了管理过程中的用户注册登录、个人信息修改、用户信息、渔船信息、渔船航班、海货价格、渔船海货、非法举报、渔船黑名单等功能。该系统操…

Elasticsearch安装Windows版

目录 1.:下载安装包,选择指定的版本,这里选择了7.8.0,官网下载地址: ​编辑 2:下载好之后解压,解压之后是这样的: 3:配置环境变量,跟JDK一样,…

rime中州韵小狼毫 联想词组 滤镜

教程目录:rime中州韵小狼毫须鼠管安装配置教程 保姆级教程 100增强功能配置教程 在 rime中州韵小狼毫 自定义词典 一文中,我们分享了如何在rime中州韵小狼毫须鼠管输入法中定义用户自定义词典;通过自定义词典,我们可以很方便的在…

*(长期更新)软考网络工程师学习笔记——Section 22 无线局域网

目录 一、IEEE 802.11的定义二、IEEE 802.11系列标准三、IEEE 802.11的两种工作模式四、CDMA/CA协议(一)CDMA/CA协议的定义(二)CDMA/CA协议的过程 五、AC与AP(一)接入控制器AC(二)无…

MySQL解决海量数据和并发性的方案——分库分表

分库分表其实是两个事情,为了解决的东西实际上也是两个,但是一定要注意,不到最后万不得已,不要用分库分表,因为这会对数据查询有极大限制。 数据量太大查询慢的问题。 这里面我们讲的「查询」其实 主要是事务中的查询…

如何实现图片压缩

文章目录 1、canvas实现图片压缩2、其他 1、canvas实现图片压缩 canvas 实现图片压缩,主要是使用 canvas 的drawImage 方法 具体思路 拿到用户上传的文件转成base64创建一个 Image,主要是获取到这个图片的宽度和高度创建一个 2D 的画布,画布…

一文搞懂系列——Linux C线程池技术

背景 最近在走读诊断项目代码时,发现其用到了线程池技术,感觉耳目一新。以前基本只是听过线程池,但是并没有实际应用。对它有一丝的好奇,于是趁这个机会深入了解一下线程池的实现原理。 线程池的优点 线程池出现的背景&#xf…

RocketMQ源码阅读-Message拉取与消费-Broker篇

RocketMQ源码阅读-Message拉取与消费-Broker篇 1. ConsumeQueue是什么2. Message重放2.1 从MappedFile文件读取Message到ConsumeQueue2.2 ConsumeQueue持久化 3. Broker提供的拉取接口3.1 请求Header3.2 拉取消息接口3.3 拉取失败处理 4. Broker提供的更新消费进度接口5. Broke…