当前位置: 首页 > article >正文

【数据结构】_以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.kler.cn/a/522522.html

相关文章:

  • 1.26学习
  • k8s支持自定义field-selector spec.hostNetwork过滤
  • 【信息系统项目管理师-选择真题】2010上半年综合知识答案和详解
  • ResNeSt: Split-Attention Networks论文学习笔记
  • 树状数组讲解
  • 如何把obsidian的md文档导出成图片,并加上文档属性
  • 每日一道算法题
  • 第05章 06 VTK标量算法中的Contouring算法
  • 【Linux网络编程】数据链路层
  • 计算机组成原理(2)王道学习笔记
  • 基于Flask的全国奶茶饮品加盟及门店数据分析系统的设计与实现
  • QT中给界面设置qss样式
  • 浅谈Linux 权限、压缩、进程与服务
  • 锐捷EWEB /auth 远程命令执行漏洞复现(附脚本)
  • 01.双Android容器解决方案
  • 【135. 分发糖果 困难】
  • 关联传播和 Python 和 Scikit-learn 实现
  • LeetCode热题100(一)—— 1.两数之和
  • Autogen_core: Reflection
  • Nuxt:利用public-ip这个npm包来获取公网IP
  • C#字典Dictionary用法详解
  • TikTok 推出了一款 IDE,用于快速构建 AI 应用
  • leetcode 1750. 删除字符串两端相同字符后的最短长度
  • 双选会资料录入步骤
  • 什么是卷积神经网络?
  • linux实际中的常用命令