【数据结构】_以SLTPushBack(尾插)为例理解单链表的二级指针传参

目录

1. 第一版代码

2. 第二版代码

3. 第三版代码


前文已介绍无头单向不循环链表的实现,详见下文:

【数据结构】_不带头非循环单向链表-CSDN博客

但对于部分方法如尾插、头插、任意位置前插入、任意位置前删除的相关实现,其形参均采用了二级结构体指针类型。

本文以尾插为例,分析单链表的二级指针传参方法的实现逻辑。

1. 第一版代码

当参数为一级指针时,phead用于接收实参传递的链表结点指针:

void SLTPushBack(SLTNode* phead, SLTDataType x) {SLTNode* newNode = CreatSLTNode(x);SLTNode* cur = phead;while (cur->next) {cur = cur->next;}cur->next = newNode;
}

考虑链表为空的情况:

当链表为空(即没有链表结点)时,头指针phead为空,用于遍历结点的指针pcur也被赋值为空,对于遍历找尾时的while (cur->next)需要对cur进行解引用,此时就会出错,故需单独对链表进行判空操作

2. 第二版代码

void SLTPushBack(SLTNode* phead, SLTDataType x) {SLTNode* newNode = CreatSLTNode(x);// 空链表if (phead == NULL) {phead = newNode;}else {// 非空链表SLTNode* cur = phead;while (cur->next) {cur = cur->next;}cur->next = newNode;}
}

编写测试函数:

void Test2() {SLTNode* plist = NULL;SLTPushBack(plist, 1);SLTPrint(plist);
}

 调用后,运行结果如下:

调试发现:当SLTPushBack执行结束后,形参的phead值按照预想被成功赋值,而实参plist并未发生改变:

这就是传值调用的问题:采用与形参同类型的形参来接收实参,在函数内可实现形参的改变,但无法改变实参。

需要改变一级结构体指针型变量plist,则需使用传址调用,故而SLTPushBack的参数除结点数据x外,另一个参数需为二级结构体指针变量:SLTNode** pphead

3. 第三版代码

将SLTPushBack的参数变更为SLTNode** pphead后,对比以下3个变量*plist、plist、&plist如下:

(1)*plist:第一个结点;

(2)plist = *pphead:指向第一个结点的指针;

(3)&plist = pphead:指向第一个结点的指针的地址;

void SLTPushBack(SLTNode** pphead, SLTDataType x) {assert(pphead);SLTNode* newNode = CreatSLTNode(x);// 空链表if (*pphead == NULL) {*pphead = newNode;}else {// 非空链表SLTNode* cur = *pphead;while (cur->next) {cur = cur->next;}cur->next = newNode;}
}

同时请注意,由于需对pphead进行解引用操作,故需保证pphead不为空,加断言即可; 

此时再调用测试函数,运行结果如下:

注:1、本文仅是做具体分析,在实际编写方法时仅需考虑该操作是否涉及实参值的改变,就可判断出到底需要传值还是传址。

对于单链表来说,由于测试时首先创建了一个结构体指针变量plist,令其指向单链表的头结点,并且plist会作为实参。

故而判断其方法是否需要传二级指针,只需考虑该方法是否可能导致链表的头结点发生替换(即头结点指针是否会发生变化)

(1)对于头插、指定位置插入、头删、尾删、指定位置删除等方法都需使用二级指针,因为可能会令新插入的结点作为头结点,或是删除了原本是头结点的结点

(2)对于指定位置插入、指定位置删除都无需使用二级指针,因为并不会导致链表头结点指针的变化

2、关于传值调用与传址调用,在C语言的指针部分已有过相关介绍:

【C语言】_传值调用与传址调用_c语言选址调用-CSDN博客文章浏览阅读275次,点赞8次,收藏4次。1、传址调用可以让函数和主调函数之间建立真正的联系,在函数内部可以修改主调函数中的变量;但实参a与形参x,实参b与形参y的地址并不相同,即各自占用其内存空间,可见虽然形参x接收了实参a的值,形参y接收了实参b的值;使用tmp交换x与y并不能实现a与b的交换;_c语言选址调用https://blog.csdn.net/m0_63299495/article/details/144946598https://blog.csdn.net/m0_63299495/article/details/144946598https://blog.csdn.net/m0_63299495/article/details/144946598只是当参数类型较为复杂,尤其是实参为指针类型变量时,可能会忽略或混淆传值调用与传址调用的相关判断。

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

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

相关文章

vue项目中,如何获取某一部分的宽高

vue项目中,如何获取某一部分的宽高 在Vue项目中,如果你想要获取某个DOM元素的宽度和高度,可以使用原生的JavaScript方法或者结合Vue的特性来实现。以下是几种常见的方法: 使用ref属性 你可以给需要测量宽高的元素添加一个ref属…

【Samba】Ubuntu20.04 Windows 共享文件夹

【Samba】Ubuntu20.04 Windows 共享文件夹 前言整体思路检查 Ubuntu 端 和 Windows 网络通信是否正常创建共享文件夹安装并配置 Samba 服务器安装 Samba 服务器创建 Samba 用户编辑 Samba 配置文件重启 Samba 服务器 在 Windows 端 访问 Ubuntu 的共享文件夹 前言 本文基于 Ub…

Linux初识——基本指令(2)

本文将继续从上篇末尾讲起,讲解我们剩下的基本指令 一、剩余的基本指令 1、mv mv指令是move(移动)的缩写,其功能为:1.剪切文件、目录。2.重命名 先演示下重命名,假设我想把当前目录下的di34改成dir5 那…

函数与方法

具名函数 具名函数是有名称的函数,可以在定义之前或之后调用。 特点 有函数名。定义后可以多次调用。便于调试,因为在调用栈中可以看到函数名。 function add(a, b) {return a b; }console.log(add(2, 3)); // 输出: 5 匿名函数 匿名函数没有名称…

定制Centos镜像(一)

环境准备: 一台最小化安装的干净的系统,这里使用Centos7.9,一个Centos镜像,镜像也使用Centos7.9的。 [rootlocalhost ~]# cat /etc/system-release CentOS Linux release 7.9.2009 (Core) [rootlocalhost ~]# rpm -qa | wc -l 306 [rootloca…

Android - 通过Logcat Manager简单获取Android手机的Log

由于工作需要,经常需要获取Android手机的Log。 平常都是通过adb命令来获取,每次都要写命令。 偶然的一个机会,我从外网发现了一个工具 Logcat Manager,只需要通过简单的双击即可获取Android的Log,这里也分享一下。 目…

c++学习第十三天

创作过程中难免有不足,若您发现本文内容有误,恳请不吝赐教。 提示:以下是本篇文章正文内容,下面案例可供参考 一、vector 1.介绍 1. vector是表示可变大小数组的序列容器。 2. 就像数组一样,vector也采用的连续存储空…

「数学::质数」分解质因子 / LeetCode 2521(C++)

概述 由算数基本定理,我们知道任意一个大于1的自然数可以表示为一些质数的乘积: LeetCode 2521: 给你一个正整数数组 nums ,对 nums 所有元素求积之后,找出并返回乘积中 不同质因数 的数目。 注意: 质数 是…

docker-compose Zookeeper 集群搭建

文章目录 前言docker-compose Zookeeper 集群搭建1. Zookeeper下载2. 制作Dockerfile文件3. 构建镜像4. docker-compose 管理5. docker-compose构建/启动6. 验证6.1 docker ps6.2 使用 zkCli.sh 连接并验证集群 前言 如果您觉得有用的话,记得给博主点个赞&#xff0…

Vue.js 使用 Vuex 管理组件间的共享状态

Vue.js 使用 Vuex 管理组件间的共享状态 今天咱们来聊聊如何用 Vuex 来管理 Vue.js 应用中各个组件之间的共享状态。如果你曾经在项目中为了让组件共享数据而头疼,那么这篇文章就是为你准备的。 什么是 Vuex? 简单来说,Vuex 就是 Vue.js 的…

WIN11 UEFI漏洞被发现, 可以绕过安全启动机制

近日,一个新的UEFI漏洞被发现,可通过多个系统恢复工具传播,微软已经正式将该漏洞标记为追踪编号“CVE-2024-7344”。根据报告的说明,该漏洞能让攻击者绕过安全启动机制,并部署对操作系统隐形的引导工具包。 据TomsH…

R语言学习笔记之高效数据操作

一、概要 数据操作是R语言的一大优势,用户可以利用基本包或者拓展包在R语言中进行复杂的数据操作,包括排序、更新、分组汇总等。R数据操作包:data.table和tidyfst两个扩展包。 data.table是当前R中处理数据最快的工具,可以实现快…

本地大模型编程实战(04)给文本自动打标签

文章目录 准备实例化本地大模型情感分析更精细的控制总结代码 使用本地大模型可以根据需要给文本打标签,本文介绍了如何基于 langchain 和本地部署的大模型给文本打标签。 本文使用 llama3.1 作为本地大模型,它的性能比非开源大模型要查一下,…

视频外绘技术总结:Be-Your-Outpainter、Follow-Your-Canvas、M3DDM

Diffusion Models专栏文章汇总:入门与实战 前言:视频Inpaint的技术很火,但是OutPaint却热度不高,这篇博客总结比较经典的几篇视频Outpaint技术。其实Outpaint在runway等工具上很火,可是学术界对此关注比较少,博主从这三年的顶会中找到了最具代表性的三篇论文解读。 目录 …

Java对象注入的常见方式

在 Java 中,对象注入(依赖注入,Dependency Injection)是实现松耦合设计的重要方式,常见的有以下几种实现形式: 1. 构造器注入(Constructor Injection) 通过类的构造函数注入依赖对象…

【数据结构】 并查集 + 路径压缩与按秩合并 python

目录 前言模板朴素实现路径压缩按秩合并按树高为秩按节点数为秩 总结 前言 并查集的基本实现通常使用森林来表示不同的集合,每个集合用一棵树表示,树的每个节点有一个指向其父节点的指针。 如果一个节点是它自己的父节点,那么它就是该集合的代…

低代码系统-产品架构案例介绍、得帆云(八)

产品名称 得帆云DeCode低代码平台-私有化 得帆云DeMDM主数据管理平台 得帆云DeCode低代码平台-公有云 得帆云DePortal企业门户 得帆云DeFusion融合集成平台 得帆云DeHoop数据中台 名词 概念 云原生 指自己搭建的运维平台,区别于阿里云、腾讯云 Dehoop 指…

.NET 8 项目 Docker 方式部署到 Linux 系统详细操作步骤

本文将详细介绍如何将一个 .NET 8 项目通过 Docker 部署到 Linux 系统中。以下步骤包括从项目的创建、Dockerfile 的编写、镜像构建、到最后在 Linux 上的容器运行。 1. 环境准备 在开始之前,请确保你已经具备以下环境: Linux 系统(如 Ubu…

【PyTorch】5.张量索引操作

目录 1. 简单行、列索引 2. 列表索引 3. 范围索引 4. 布尔索引 5. 多维索引 个人主页:Icomi 在深度学习蓬勃发展的当下,PyTorch 是不可或缺的工具。它作为强大的深度学习框架,为构建和训练神经网络提供了高效且灵活的平台。神经网络作为…

springboot 动态线程池

在Spring Boot中,可以使用ThreadPoolTaskExecutor类来创建动态线程池。以下是一个示例: 首先,需要在配置文件中配置线程池的属性,例如最小线程数、最大线程数、线程存活时间等。可以在application.properties或application.yml中…