P8 删除链表指定节点

前言
                                     

🎬 个人主页:@ChenPi

🐻推荐专栏1: 《C++_@ChenPi的博客-CSDN博客》✨✨✨ 

🔥 推荐专栏2: 《Linux C应用编程(概念类)_@ChenPi的博客-CSDN博客》✨✨✨

📝推荐专栏3: ​​​​​​《 链表_@ChenPi的博客-CSDN博客》 ✨✨✨
🍉本篇简介  :  链表数据插入之尾插法

✨ 只有我努力了 才有机会接触成功✨

链表是一种常见的基础数据结构,结构体指针在这里得到了充分的利用。链表可以动态的进行存储分配,也就是说,链表是一个功能极为强大的数组,他可以在节点中定义多种数据类型,还可以根据需要随意增添,删除,插入节点。链表都有一个头指针,一般以head来表示,存放的是一个地址。链表中的节点分为两类,头结点和一般节点,头结点是没有数据域的。链表中每个节点都分为两部分,一个数据域,一个是指针域。说到这里你应该就明白了,链表就如同车链子一样,head指向第一个元素:第一个元素又指向第二个元素;……,直到最后一个元素,该元素不再指向其它元素,它称为“表尾”,它的地址部分放一个“NULL”(表示“空地址”),链表到此结束。

作为有强大功能的链表,对他的操作当然有许多,比如:

  1. 链表的创建
  2. 链表的链表的遍历打印数据
  3. 链表里面的结构体数据的修改
  4. 链表节点的删除
  5. 链表插入新节点
  6. 链表的数据排序
  7. 链表的反序
  8. 清空链表的元素
  9. 求链表的长度等

在前面几章,我们学习了 

  1. 链表的创建
  2. 链表的链表的遍历打印数据
  3. 链表里面的结构体数据的修改
  4. 求链表的长度等
  5. 还有链表结尾插入数据节点,非指定节点
  6. 链表指定节点后方插入数据
  7. 链表头插入新节点以及头插法创建链表

 对链表的操作我们还差链表指定节点的删除,反序以及清空链表

这章我们学习链表指定节点删除

01 链表删除指定节点

首先,我们先确定函数的大致操作

我们定义一个函数名为deleteHeadLinkNode

有两参数,参数1为链表的头节点,参数2为一个整形变量的索引NodeIndex

索引值则是要删除的节点,如索引值等于1,择删除第一个节点

返回值则是一个结构体指针,返回值为链表头的地址

struct Link * deleteHeadLinkNode(struct Link *head,int NodeIndex)
{

}

函数体大致这样,首先,我们要判断索引值是否越界

/*获取链表的节点数*/
int GetLinkNum(struct Link *head)
{
	struct Link *prev = head;
	int count = 0;
	while (prev != NULL)
	{
		count++;
		prev = prev->next;
	}
	return count;
}

struct Link * deleteHeadLinkNode(struct Link *head,int NodeIndex)
{
	struct Link *prev = head;   //保存头节点的地址
	if(NodeIndex > GetLinkNum(prev)||(NodeIndex<0))   //判断是否越界
	{
		printf("ERROR: Link index out of range");
		return NULL;
	}
}

上面这段代码为检测索引值有没有越界,越界的意思是,比如我链表的长度为5,当传进来的索引值为7,那链表总共就5个节点,这么删除第七节点嘛,所以越界了

其实其中的每一部分都可以写成一个函数了,这样模块话,可以减少很多功夫,我们下一章在讲模块化的问题把

现在我们看上面图的第二个红框框,这部分就是删除链表的头节点了,我们分析下代码

当索引值为1的时候,我们让链表的头节点等于链表头的下一个节点就可以

然后释放prev

prev在第一个红框里已经被指向头节点

第三个红框框则是本章的重点了,因为我们创建链表是在堆中创建的,属于是动态创建的链表

所以我们释放要删除的节点要格外小心

不然就很容易出BUG

首先我们要定义一个结构体的指针prior,指向用于保存前节点的地址,然后就是遍历

定义整形变量记录目前遍历到第几节点,如果找到了目标节点,判断是否为链表尾

如果是,就让保存的前节点的next等于NULL就行,然后释放prev

正常节点也如此

我们测试一下,我们调用函数,删除第二节点,我们看下打印,从 4 2 5 3变为4 5 3了,第二节点已经被释放 

测试代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct Link
{
	int data;
	struct Link *next;
};

/*打印链表数据*/
void PrintLink(struct Link *head)
{
	struct Link *prev = head;
	while (NULL != prev) 
	{
		printf("%d  ", prev->data);
		prev = prev->next;
	}
	printf("\n");
}

/*获取链表的节点数*/
int GetLinkNum(struct Link *head)
{
	struct Link *prev = head;
	int count = 0;
	while (prev != NULL)
	{
		count++;
		prev = prev->next;
	}
	return count;
}

struct Link *getHead(int data)
{
	struct Link* head = (struct Link*)malloc(sizeof(struct Link));
	head->data = data;
	head->next = NULL;
	return head;
}

/* 链表头插入数据,不指定位置*/
struct Link* frontInsertDataLink(struct Link *head, int data)
{
	struct Link *prev = head;
	struct Link *newLink = (struct Link *)malloc(sizeof(struct Link));
	newLink->data = data;
	newLink->next = prev;
	return newLink;
}

struct Link *frontInsertNodeDataLink(struct Link *head,int NodeIndex,int data)
{
	struct Link *prev = head;
	int cnt = 1;
	if(NodeIndex > GetLinkNum(prev)||(NodeIndex<0))
	{
		printf("ERROR: Link index out of range");
		return NULL;
	}
	else if (NodeIndex == 1)
	{
		prev = frontInsertDataLink(prev,data);
		return prev;
	}
	while (NULL != prev->next)
	{
		if(cnt == NodeIndex-1)
		{
			struct Link *newLink = (struct Link *)malloc(sizeof(struct Link));
			newLink->data = data;
			newLink->next = prev->next;
			prev->next = newLink;
			return head;
		}
		cnt++;
		prev = prev->next;
	}
	return NULL;
}


struct Link * deleteHeadLinkNode(struct Link *head,int NodeIndex)
{
	struct Link *prev = head;   //保存头节点的地址
	int cnt = 1;
	if(NodeIndex > GetLinkNum(prev)||(NodeIndex<0))   //判断是否越界
	{
		printf("ERROR: Link index out of range");
		return NULL;
	}


	if(1 == NodeIndex)   //如果要删除头节点
	{
		head = head->next;
		free(prev);
		return head;
	}

	struct Link *prior = NULL;   //遍历时用来保留前一个节点的状态
	while (NULL != prev)   //判断是不是最后一个节点
	{
		prior = prev;//用来保留前一个节点的状态
		prev = prev->next;   //走向下一个节点,也就是循环增量

		if(cnt == NodeIndex-1)  //找到需要删除的节点
		{
			if(NULL == prev->next)    //1.如果找到的是尾节点
			{
				prior->next = NULL;       //原来尾节点的前一个为节点变成了新尾节点
				free(prev);        //释放原来尾节点的内存
				return head;
			}
			else    //如果找到的是普通节点
			{
				prior->next = prev->next;   //要删除的节点的前一个节点和后一个节点相连
				free(prev);
				return head;
			}
		}
		cnt++;
	}
	return NULL;   //没找到对应节点,操作失败,返回NULL
}

int main()
{
	struct Link *head = getHead(3);
	head = frontInsertDataLink(head, 5); 
	head = frontInsertDataLink(head, 2); 
	PrintLink(head);
	head = frontInsertNodeDataLink(head, 1,4);
	PrintLink(head);
	head = deleteHeadLinkNode(head,2);
	PrintLink(head);
	return 0;
}

我们下一期写一下 清空链表吧

🌺对您有帮助的话记得点赞加关注


🌺如果有说的不对的欢迎指正

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【眼界 | 每日技术】日常生活中的那些技术,增长眼界系列(一)

&#x1f935;‍♂️ 个人主页: AI_magician &#x1f4e1;主页地址&#xff1a; 作者简介&#xff1a;CSDN内容合伙人&#xff0c;全栈领域优质创作者。 &#x1f468;‍&#x1f4bb;景愿&#xff1a;旨在于能和更多的热爱计算机的伙伴一起成长&#xff01;&#xff01;&…

腾讯云双十二优惠活动有哪些?详细攻略来了!

腾讯云作为全球领先的云计算服务提供商&#xff0c;一直在为各行各业的用户提供优质、高效、稳定的云计算服务。双十二即将来临&#xff0c;腾讯云也为大家准备了一系列丰富多彩的优惠活动。那么&#xff0c;这些优惠活动究竟有哪些&#xff1f;详细攻略在此&#xff0c;一起来…

电源需要考虑的因素

做产品的都离不开电源&#xff0c;产品出问题也首先检查供电是否正常。今天给大家分享的是做好一个电源需要考虑哪些因素。 一&#xff0e; 描述输入电压影响输出电压几个指标形式 1&#xff0e; 稳压系数 A&#xff0e;稳压系数&#xff1a;表示负载不变时&#xff0c;稳压电源…

正运动技术EtherCAT扩展模块接线参考以及使用流程

本文以正运动扩展模块EIO16084为例 一、EtherCAT扩展模块接线参考 EIO16084数字量扩展模块为单电源供电&#xff0c;主电源就可以给IO供电&#xff0c;主电源采用24V直流电源。 EIO16084扩展模块在扩展接线完成后&#xff0c;不需要进行进行二次开发&#xff0c;只需手动在E…

用CHAT如何写教研室工作总结?

问CHAT&#xff1a;写一份教研室工作总结 CHAT回复&#xff1a;以下是一个教研室工作总结的大纳&#xff0c;具体内容需要根据你们教研室的实际情况进行填充和修改。 教研室XXXX年度工作总结 1. 引言&#xff1a;简要介绍本年度工作总结的目的和主题。 2. 教育教学工作&…

第一节:安装

Node.js 命令行的TypeScript编译器可以使用Node.js包来安装。 安装 npm install -g typescript 编译 tsc helloworld.ts 由于无法直接运行TypeScript ,所以会将 ts文件 转换成 js文件&#xff0c; 生成一个 js 的文件&#xff1b; 也可以安装 ts-node &#xff0c;他是封…

树_左叶子之和

//给定二叉树的根节点 root &#xff0c;返回所有左叶子之和。 // // // // 示例 1&#xff1a; // // // // //输入: root [3,9,20,null,null,15,7] //输出: 24 //解释: 在这个二叉树中&#xff0c;有两个左叶子&#xff0c;分别是 9 和 15&#xff0c;所以返回 24 //…

vue3中使用全局事件总线通信

全局事件总线通信可以用于多个组件之前相互通信,包括但不限于父子、兄弟组件间通信。 注意1&#xff1a;emit分发和on接收 需要在onMounted或之后的生命周期执行&#xff0c;否则无效。 注意2&#xff1a;刷新页面后&#xff0c;已更新的数据将回到初始值。 .emit(事件名, 参…

操作系统·虚拟存储器

局部性原理&#xff1a;时间、空间的局部性 虚拟存储器的原理&#xff1a; 只将当前执行需要的部分页或段读入到内存&#xff0c;让程序开始执行。 执行过程中&#xff0c;如果需执行的指令或访问的数据未在内存&#xff08;称为缺页或缺段&#xff09;&#xff0c;则由处理器…

Java中实用的策略模式【Strategy】

一、简介 我们知道Java中有许多的设计模式&#xff0c;总共32个左右。常见的比如简单工厂、建造者、原型、代理、桥接等&#xff0c;这些设计模式相当于是一个规范&#xff0c;主要是总结出来便于大家理解开发的一种算法思路。 今天主要是给大家介绍一下我们常见的策略模式&a…

向库存抢利润!DigiOS微服务“库存中心”能力解读

作者&#xff1a;徐礼昭&#xff08;商派市场负责人&#xff0c;重构零售实验室负责人&#xff09; 同一件SKU&#xff0c;在不同渠道往往会出现“超卖”和“滞销”两种截然不同的情况。如何及时合理的调拨库存&#xff0c;实现产品的最大化销售&#xff08;降低库存成本&#…

智能优化算法应用:基于动物迁徙算法无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于动物迁徙算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于动物迁徙算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.动物迁徙算法4.实验参数设定5.算法结果6.参考…

揭秘强化学习:Python 实践指南

一、说明 强化学习 (RL) 是机器学习和人工智能 (AI) 的一个子领域&#xff0c;专注于开发能够通过与环境交互进行学习的智能代理。与传统的监督和无监督学习不同&#xff0c;强化学习主要关注动态、顺序环境中的决策。它在人工智能中具有重要意义&#xff0c;特别是在自主代理必…

EasyRecovery14破解版官方软件安装包下载

Ontrack EasyRecovery 是一款功能强大的数据恢复软件&#xff0c;它可以帮助用户从各种存储设备中恢复丢失或删除的数据。它支持多种文件系统和文件类型&#xff0c;可以恢复包括照片、视频、音频、文档、电子邮件和归档文件等不同类型的数据。 Ontrack EasyRecovery 是一款非常…

基于Arduino的音乐喷泉设计(论文+源码)

1.系统设计 整个Audio Visualizer系统通过锂电池电源进行供电&#xff0c;当Arduino控制板通过蓝牙音频接收器模块与手机蓝牙完成匹配后&#xff0c;然后通过蓝牙音频接收器模块接收来自手机的音乐&#xff0c;接着通过对音乐进行FFT变换来得到音乐的频率数据&#xff0c;接着…

Java——》JSONObjet 数据顺序

推荐链接&#xff1a; 总结——》【Java】 总结——》【Mysql】 总结——》【Redis】 总结——》【Kafka】 总结——》【Spring】 总结——》【SpringBoot】 总结——》【MyBatis、MyBatis-Plus】 总结——》【Linux】 总结——》【MongoD…

Python小项目:葛兰中欧医疗基金数据分析

1 前言 2022年1月末&#xff0c;正值年前&#xff0c;股票市场持续大幅下跌&#xff0c;与之相应的基金市场也出现了近一周的持续跌势。作为一个资深的投资者&#xff0c;我承认自己曾是一名“韭菜”&#xff0c;在2021年12月初购买了中欧医疗健康混合C基金。这只基金由医疗板…

Anaconda详细安装步骤图文教程

文章目录 前言一、什么是Anaconda?二、为什么安装Anaconda三、如何安装AnacondaAnaconda关于Python技术储备一、Python所有方向的学习路线二、Python基础学习视频三、精品Python学习书籍四、Python工具包项目源码合集①Python工具包②Python实战案例③Python小游戏源码五、面试…

quickapp_快应用_父子组件传值

目录 页面级组件自定义组件(子组件)引入自定义组件(子组件)父组件给子组件传值子组件给父组件进行传值父组件调用子组件的方法 页面级组件 在pages中定义的组件被称为页面级组件。 页面级组件(等同于Vue页面)&#xff0c;通过路由配置可以进行页面跳转。 自定义组件(子组件)…

InnoDB的B+树索引(一)

文章目录 概要一、InnoDB行格式二、InnoDB数据页结构2.1 User Records2.2 两个虚拟行记录2.3 PageDirectory&#xff08;页目录&#xff09;2.4 File Header&#xff08;文件头部&#xff09; 三、B树索引3.1 B树索引结构3.2 先有根节点再有叶子节点3.3 一条记录在索引中的查找…