707. 设计链表 链表的知识复习

707. 设计链表

class MyLinkedList {public:struct LinkedNode {int val;LinkedNode *next;LinkedNode(int val):val(val),next(nullptr){}};MyLinkedList(){dummyhead = new LinkedNode(0);size=0; }int get(int index) {if(index < 0 || index >= size){return -1;}LinkedNode * cur = dummyhead->next;//注意这里cur指针的指向是哪儿,画图判断逻辑是否是正确的。while(index--){//初始化要放在外面 ListNode * cur = dummyhead;cur = cur->next;}// return cur->next->val;return cur->val;}void addAtHead(int val) {LinkedNode * newNode = new LinkedNode(val);newNode->next = dummyhead->next;dummyhead->next = newNode;size++;}void addAtTail(int val) {LinkedNode *newNode = new LinkedNode(val);LinkedNode *cur = dummyhead;while(cur->next != nullptr){cur= cur->next;}cur->next = newNode;size++;}void addAtIndex(int index, int val) {if(index > size || size < 0) return ;// if(index == size ){//     addAtTail(val);//     return;// }LinkedNode * newNode = new LinkedNode(val);LinkedNode *cur=dummyhead;while(index--){cur=cur->next;}newNode->next = cur->next;cur->next= newNode;size++;}void deleteAtIndex(int index) {if(index<0||index>= size){return;}LinkedNode*cur=dummyhead;while(index--){cur= cur->next;}LinkedNode *temp= cur->next;cur->next = cur->next->next;delete temp;size--;temp =nullptr;}
private:
int size;
LinkedNode * dummyhead;
};/*** Your MyLinkedList object will be instantiated and called as such:* MyLinkedList* obj = new MyLinkedList();* int param_1 = obj->get(index);* obj->addAtHead(val);* obj->addAtTail(val);* obj->addAtIndex(index,val);* obj->deleteAtIndex(index);*/

这三个构造函数在 ListNode 结构体中定义的作用和用法有所不同,它们分别处理了不同的初始化场景。我们来逐一分析这三个构造函数的区别:

1. 默认构造函数

ListNode() : val(0), next(nullptr) {}
  • 作用:这是一个 默认构造函数,用于在不提供任何参数的情况下创建 ListNode 对象。

  • 初始化

    • val(0):将节点的 val 初始化为 0
    • next(nullptr):将节点的 next 指针初始化为 nullptr,意味着该节点不指向任何其他节点。
  • 用途:如果你只是创建一个空的节点(没有指定值或下一个节点),使用这个构造函数非常方便。比如:

    ListNode node; // 创建一个 val 为 0, next 为 nullptr 的节点
    

2. 带一个参数的构造函数

ListNode(int x) : val(x), next(nullptr) {}
  • 作用:这是一个 带一个参数的构造函数,用于在创建节点时指定 val 的值,但不指定 next,即将 next 指向 nullptr

  • 初始化

    • val(x):将节点的 val 初始化为传入的参数 x
    • next(nullptr):将节点的 next 指针初始化为 nullptr,意味着该节点没有连接到其他节点。
  • 用途:当你创建一个节点,并且只关心它的值而不关心它的 next 指针时使用这个构造函数。例如:

    ListNode node(5); // 创建一个 val 为 5, next 为 nullptr 的节点
    

3. 带两个参数的构造函数

ListNode(int x, ListNode* next) : val(x), next(next) {}
  • 作用:这是一个 带两个参数的构造函数,用于在创建节点时同时指定 valnext

  • 初始化

    • val(x):将节点的 val 初始化为传入的参数 x
    • next(next):将节点的 next 指针初始化为传入的参数 next,即指向另一个 ListNode 对象。这个参数通常是指向另一个链表节点的指针,表示该节点的 "下一个" 节点。
  • 用途:当你需要创建一个包含特定值且与其他节点连接的节点时使用。例如:

    ListNode* node3 = new ListNode(3);
    ListNode* node2 = new ListNode(2, node3); // 创建一个 val 为 2 的节点,它的 next 指向 node3
    

    在这个例子中,node2val2next 是指向 node3 的指针,node3val3nextnullptr


总结

  • 默认构造函数:不带任何参数,创建一个 val0nextnullptr 的节点。
  • 带一个参数的构造函数:只传入一个 val 参数,next 默认为 nullptr。常用于创建值已知但不关心 next 的节点。
  • 带两个参数的构造函数:同时传入 valnext,用于创建值已知并且与其他节点连接的节点。

这三种构造函数提供了不同的初始化方式,使得你可以灵活地创建和管理链表节点,特别是在处理链表时。

是的,虚拟头节点(dummy head)会作为链表中的第一个节点,但它的作用并不是作为链表数据的 "实际头节点"。它的存在是为了简化链表的操作,尤其是在插入和删除节点时避免处理空链表或单节点链表时的特殊情况。

虚拟头节点的作用

在链表中,特别是单向链表,在执行插入和删除操作时,往往需要特殊处理头节点,尤其是在头节点是空时。例如:

  • 删除头节点:你需要把头节点的指针指向第二个节点。
  • 插入新节点到头部:你需要更新头节点的指针。

这些操作如果没有虚拟头节点,可能会导致一些复杂的边界条件需要单独处理,增加代码的复杂性。

通过虚拟头节点,简化了这些边界条件的处理:
  • 无论链表是否为空,操作都变得统一。虚拟头节点总是存在的,插入和删除操作都可以直接从虚拟头节点开始,避免了处理空链表或只有一个节点的特殊情况。

虚拟头节点的工作原理

  1. 初始化时

    • MyLinkedList() 构造函数中通过 new LinkedNode(0) 创建一个值为 0 的虚拟头节点,并将 _dummyHead 指向它。
    • 这个节点的 next 指针初始为 nullptr,表示链表为空。
  2. 链表的操作

    • 例如,当你插入一个节点时,不需要检查链表是否为空,只需从虚拟头节点开始。
    • 例如,在插入新节点时(addAtHead),你只需将虚拟头节点的 next 指针指向新节点。
    • 这样,无论链表是空的,还是有节点,代码的逻辑都很简单。

虚拟头节点如何作为第一个节点?

即使虚拟头节点是链表中的第一个节点,它本身并不存储有效数据。它的 val 通常不被使用或不重要,它只是为了简化链表操作而存在。

  • 链表中的第一个有效节点 是紧随虚拟头节点之后的节点。虚拟头节点只是在链表结构中占据一个位置,用来保持链表的一致性和简化操作。

举个例子

假设你通过 addAtHead 函数添加一个新节点 5 到链表中:

list.addAtHead(5);  // 向链表头部添加一个节点,值为 5

在调用 addAtHead(5) 后,链表结构会变成:

虚拟头节点 (val=0) → 新节点 (val=5) → nullptr
  • 这里的虚拟头节点的值 0 是无关紧要的,它的作用只是作为链表的 "头" 节点。
  • 第一个有效的节点是 val=5 的节点,它是链表中的实际数据节点。

如何理解链表中的头节点

  • 链表的头节点(head node)通常指向链表中的第一个有效数据节点。
  • 虚拟头节点(dummy head)是为了方便链表操作而引入的,通常它的值是无关紧要的。

总结

  • 虚拟头节点MyLinkedList 类中是一个特殊的辅助节点,它是链表结构的一部分。
  • 在初始化时,虚拟头节点被创建并赋值给 _dummyHead,但它并不包含有效数据。
  • 链表的第一个有效数据节点 是虚拟头节点的 next 指向的节点。
  • 通过引入虚拟头节点,链表的插入和删除操作变得更简洁、统一。

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

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

相关文章

【中间件介绍及案例分析】

中间件介绍及案例分析 一、中间件的定义 中间件是一种位于操作系统、网络和数据库之上&#xff0c;应用软件之下的软件。它的主要作用是为处于不同系统中的软件组件提供通用服务&#xff0c;使得这些软件组件能够更好地通信、协同工作&#xff0c;并且帮助开发人员更高效地构…

题解 - 统计成绩

题目描述 每次考试或测试后&#xff0c;老师们都要进行成绩统计。假如某次期末考试有语文、数学、英语三门课&#xff0c;现请你编程输出总成绩最高分以及每门学科的最高分。 输入 输入共n1行。 第1行是一个正整数n&#xff08;1≤n≤100&#xff09;&#xff0c;表示学生人数…

Unity性能优化---使用SpriteAtlas创建图集进行批次优化

在日常游戏开发中&#xff0c;UI是不可缺少的模块&#xff0c;而在UI中又使用着大量的图片&#xff0c;特别是2D游戏还有很多精灵图片存在&#xff0c;如果不加以处理&#xff0c;会导致很高的Batches&#xff0c;影响性能。 比如如下的例子&#xff1a; Batches是9&#xff0…

环境和工程搭建

1.案例介绍 1.1 需求 实现⼀个电商平台 该如何实现呢? 如果把这些功能全部写在⼀个服务⾥, 这个服务将是巨⼤的. 巨多的会员, 巨⼤的流量, 微服务架构是最好的选择. 微服务应⽤开发的第⼀步, 就是服务拆分. 拆分后才能进⾏"各⾃开发" 1.2 服务拆分 拆分原则 …

解决Jmeter HTTP Cookie管理器cookie不生效

解决Jmeter HTTP Cookie管理器cookie不生效问题 解决Jmeter HTTP Cookie管理器cookie不生效问题1、设置Jmeter HTTP Cookie管理器cookie后&#xff0c;发起的请求显示[no cookies]jmeter问题复现&#xff1a;这里同样使用postman进行重试&#xff0c;发现是可以正常获取数据的&…

操作系统课后习题2.2节

操作系统课后习题2.2节 第1题 CPU的效率指的是CPU的执行速度&#xff0c;这个是由CPU的设计和它的硬件来决定的&#xff0c;具体的调度算法是不能提高CPU的效率的&#xff1b; 第3题 互斥性&#xff1a; 指的是进程之间的同步互斥关系&#xff0c;进程是一个动态的过程&#…

二叉搜索树 平衡树(c嘎嘎版)

定义: 二叉搜索树是一种二叉树的树形数据结构,其定义如下: 空树是二叉搜索树。 若二叉搜索树的左子树不为空,则其左子树上所有点的附加权值均小于其根节点的值。 若二叉搜索树的右子树不为空,则其右子树上所有点的附加权值均大于其根节点的值。 二叉搜索树的左右子树均为…

Everything搜索实现

最近编写NTFS文件实时搜索工具, 类似 Everything 这样, 速度快还小巧, 于是花了约3周进行研究, 总结下学习过程中一些经验 实现分3部分完成 一. 解析NTFS 主文件表(MFT) 这一步是获取文件数据的唯一迅速且可靠的来源 NTFS_MFT_Parse.h #pragma once #include "NTFS_Bas…

23.DDD与微服务

学习视频来源&#xff1a;DDD独家秘籍视频合集 https://space.bilibili.com/24690212/channel/collectiondetail?sid1940048&ctype0 文章目录 DDD与微服务的关系1. DDD可以用微服务实现&#xff0c;也可以不用微服务实现2. DDD是微服务拆分的必须参考项之一3. 微服务架构…

vscode 打开 setting.json

按下Ctrl Shift P&#xff08;Windows/Linux&#xff09;或Cmd Shift P&#xff08;Mac&#xff09;来打开命令面板。输入open settings&#xff0c;然后选择 Open User Settings(JSON)。打开settings.json文件 ------修改设置-----&#xff1a; 1、 html代码的行长度&am…

汽车电子元件的可靠性保障:AEC-Q102认证

AEC-Q102标准的起源与价值 随着汽车电子系统的日益复杂&#xff0c;电子器件必须能够在极端的温度、湿度、振动和电磁干扰等恶劣条件下保持性能。AEC-Q102标准由汽车电子委员会&#xff08;AEC&#xff09;制定&#xff0c;专门针对LED、激光二极管和光电二极管等光电器件&…

基于 Couchbase 的数仓建模方案

以下是一份基于 Couchbase 的数仓建模方案&#xff0c;结合你的业务需求&#xff08;订单、支付、退款业务&#xff09;以及报表需求&#xff08;营收报表、优惠报表、支付方式报表&#xff09;&#xff0c;为 ODS、DWD、DWS、ADS 层提供了存储方式、库名、表名的标准化设计。 …

RK3576 Android14,内存大于4G时UVC应用无法申请内存

最近有个项目需要将Linux虚拟成UVC摄像头&#xff0c;开发过程中遇到一个奇怪的事情&#xff0c;通过V4l2框架接口申请内存时&#xff0c;相同的板子&#xff0c;只是内存一个4G一个8G。4G的内存可以申请成功&#xff0c;8G就不行。提示“内存不足” 内存更大反而内存不足&…

Mongoose连接数据库操作实践

文章目录 介绍特点&#xff1a;Mongoose 使用&#xff1a;创建项目并安装&#xff1a;连接到 MongoDB&#xff1a;定义 Schema&#xff1a;创建模型并操作数据库&#xff1a;创建文档&#xff1a;查询文档&#xff1a;更新文档&#xff1a;删除文档&#xff1a;使用钩子&#x…

RK356X camera 配置

目录 一、RK356x camera硬件 Mipi接口 DVP接口 二、软件链路 三、dts配置 DVP MIPI sensor->dphy->isp_vir 一、RK356x camera硬件 RK356X包含RK3566和RK3568,在camera方面,两颗芯片的软硬件是兼容的,共有两种硬件连接方式:DVP和MIPI。 Mipi接口 图一 如图…

java集合基础

Java的java.util包主要提供了以下三种类型的集合&#xff1a; List&#xff1a;一种有序列表的集合&#xff0c;例如&#xff0c;按索引排列的Student的List&#xff1b;Set&#xff1a;一种保证没有重复元素的集合&#xff0c;例如&#xff0c;所有无重复名称的Student的Set&…

用前端html如何实现2024烟花效果

用HTML、CSS和JavaScript编写的网页&#xff0c;主要用于展示“2024新年快乐&#xff01;”的文字形式烟花效果。下面是对代码主要部分的分析&#xff1a; HTML结构 包含三个<canvas>元素&#xff0c;用于绘制动画。引入百度统计的脚本。 CSS样式 设置body的背景为黑…

批量合并多个Excel到一个文件

工作中&#xff0c;我们经常需要将多个Excel的数据进行合并&#xff0c;很多插件都可以做这个功能。但是今天我们将介绍一个完全免费的独立软件【非插件】&#xff0c;来更加方便的实现这个功能。 准备Excel 这里我们准备了两张待合并的Excel文件 的卢易表 打开的卢易表软件…

GLM4模型详解 - 智谱AI开源大模型全面解析

&#x1f4da; 2024年6月5日,智谱AI在开发者大会上正式开源GLM-4-9B系列大模型。本文将全面解析GLM4的技术特点、部署方案和应用场景。 GLM-4-9B 模型具备了更强大的推理性能、更长的上下文处理能力、多语言、多模态和 All Tools 等突出能力。 “All Tools” 一、模型概述 1.…

DataEase 开源 BI 工具 v2.10.3 LTS 发布

DataEase 开源 BI 工具 v2.10.3 LTS 发布 2024 年 12 月 9 日&#xff0c;开源 BI 工具 DataEase 正式发布 v2.10.3 LTS 版本。 此次更新带来了多方面的功能变化&#xff1a; 数据源&#xff1a;API 数据源与 Excel 数据源可设定字段类型与长度&#xff0c;优化数据接入的精准…