单链表的实现(数据结构)
一. 单链表的实现
我们在上一篇中简单的认识了链表的组成和结构,并打印出链表,那么今天就来具体实现一下单链表对于数据增加、删减、插入等。
接下来就是我们在链表中对于数据的增、删、插的实现,对于我们的链表来说在任何地方增加数据都需要来申请一个新的结点,首先呢,SLDatatype是我们更改int类型的名称之后得来的,SL是结构体的名称,我们先申请一个结构体大小的新结点node,然后再将新结点中的x的值赋给data,再让新结点的next指向NULL,申请新结点的函数写好之后我们就来写关于数据的增、删、插等,所以我们直接先来完成申请新结点的代码:
SLDatatype* SLBuyNode(SLDatatype x)
{SL* node = (SL*)malloc(sizeof(SL));if (node == NULL){perror("malloc fail!");exit(1);}node->data = x;node->next = NULL;return node;
}
尾插:
//尾插函数
void SLPuchBack(SL** pphead, SLDatatype x)
{//申请新结点//*pphead-->&plistSL* newnode = SLBuyNode(x);if (*pphead == NULL){*pphead = newnode;}else{//尾结点-->新结点SL* pcur = *pphead;//找尾结点while (pcur->next){pcur = pcur->next;}pcur->next = newnode;}}
void SLTest01()
{SL* plist = NULL;SLPuchBack(&plist, 1);SLprintf(plist);SLPuchBack(&plist, 2);SLPuchBack(&plist, 3);SLprintf(plist);
}int main()
{SLTest01();return 0;
}
在实现让任何代码之前,我们都因该将思路理清楚,尾插该注意什么,怎么去是实现?首先一定是要找到最后一个结点,pphead是我们的头结点,我们一贯会将pphead赋给一个新的指针pcur,使用while循环找到最后一个结点,但是如果while里面是pcur的那我们不就直接跳出循环,那我们还怎么找最后一个结点呢?所以我们不如使用while(pcur->next),也就是当我们pcur指向3的时候我们的next刚好指向的是NULL,停止了循环,刚好pcur还指向尾结点,然后我们在将newnode赋值给我们的最后一个结点。在上面的代码中我们要注意的一点是SLPuchBack函数中传入的是形参,这个时候我们要使用传值调用,因为如果使用传值调用的话,形参的改变并不影响实参,所以在测试函数SLTest01中传入的是&plist,然而plist本身就是一个指针,所以我们在SLPuchBack中要使用二级指针即**pphead。
头插:对于头插就简单很多,我们只需要申请一个新的结点,然后将结点与原本的头结点连接,在让pphead指向现在新的结点。
//头插函数
void SLPuchFront(SL** pphead, SLDatatype x)
{assert(pphead);SL* newnode = SLBuyNode(x);newnode->next = *pphead;*pphead = newnode;
}
尾删:对于尾删我们并不能简单的将最后一个结点删除,因为这样会让前面一个指针变成野指针,可以把最后一个结点前面的结点的next指向NULL,然后将最后一个结点释放掉。
//尾删函数
void SLPopBack(SL** pphead)
{assert(pphead && *pphead);//假如原本只有一个结点if ((*pphead)->next == NULL){free(*pphead);*pphead = NULL;}else{SL* pcur = *pphead;SL* front = NULL;while (pcur->next){front = pcur;pcur = pcur->next;}front->next = NULL;free(pcur);pcur = NULL;}
头删:
//头删函数
void SLPopFront(SL** pphead)
{assert(pphead && *pphead);SL* pcur = (*pphead)->next;free(*pphead);*pphead = pcur;
}
在指定位置之前插入数据:
void SLInsertFront(SL** pphead, SL* pos, SLDatatype x)
{assert(pphead && pos);SL* newnode = SLBuyNode(x);SL* pcur = *pphead;if (pos == *pphead){newnode->next = pos;*pphead = newnode;}else{while (pcur->next != pos){pcur = pcur->next;}newnode->next = pos;pcur->next = newnode;}}
在指定位置之后插入数据:
void SLInsertAfert(SL* pos, SLDatatype x)
{assert(pos);SL* newnode = SLBuyNode(x);newnode->next = pos->next;pos->next = newnode;
}
删除pos结点:
void SLErase(SL** pphead, SL* pos)
{assert(pphead && *pphead);assert(pos);SL* pcur = *pphead;if (pos == *pphead){SLPopFront(pphead);}else{while (pcur->next != pos){pcur = pcur->next;}pcur->next = pos->next;free(pos);pos = NULL;}
删除pos之后的结点:
void SLEraseAfert(SL* pos)
{assert(pos&&pos->next);SL* deal = pos->next;pos->next = pos->next->next;free(deal);deal = NULL;
}
销毁链表:
void SLDestroy(SL** pphead)
{SL* pcur = *pphead;while (pcur){SL* next = pcur->next;free(pcur);pcur = next;}*pphead = NULL;
}
上面关于链表的指定位置插入、删除等算法,我们要注意的就是在我们更改链表中的数据的时候,要更改的这个数据会影响其他的数据吗?如果影响我们应该怎么做,提前设置好几个指针变量还是其他的办法,寻找某一个结点的时候while循环的条件是什么,这些我们都要注意,上面已经给出较为详细的代码,大家可以参考,另外就是注意free指针之后一定要将其置为空指针NULL,单链表完成之后我们就要拿一些算法题来练手,如何使用单链表来完成一些算法题。
二. 算法题
移除链表元素
https://leetcode.cn/problems/remove-linked-list-elements/description/
这个题目是移除链表元素,我们有两个思路一个就是利用我们原本的单链表对指定位置的结点进行删除,还有就是创建一个新的链表然后将符合的元素移到新的链表中,我们可以来实现第二中思路: 创建一个新链表,遍历原链表,将不等于给定值 val 的节点依次添加到新链表中。
1. 创建新链表的哑节点(dummy node):
- 目的是简化操作,避免处理新链表头节点为空的特殊情况。
- 例如,可以创建一个值为 0 的哑节点,将其 next 指针初始化为 null 。
2. 遍历原链表:
- 从原链表的头节点 head 开始遍历。
- 检查当前节点的值是否等于 val 。
- 如果不等于 val ,则将该节点添加到新链表中。
3. 添加节点到新链表:
- 将原链表中不等于 val 的节点的 next 指针指向新链表的末尾节点的 next 。
- 更新新链表的末尾节点为该节点。
4. 返回新链表的头节点:
- 新链表的头节点为哑节点的 next 。
通过以上步骤,就可以使用创建新链表的方法删除原链表中所有值为 val 的节点,并返回新的头节点。
#include <stdio.h>
#include <stdlib.h>struct ListNode {int val;struct ListNode* next;
};struct ListNode* createNode(int val) {struct ListNode* newNode = (struct ListNode*)malloc(sizeof(struct ListNode));newNode->val = val;newNode->next = NULL;return newNode;
}struct ListNode* removeElements(struct ListNode* head, int val) {struct ListNode* dummy = createNode(0);struct ListNode* curr = dummy;while (head) {if (head->val!= val) {curr->next = head;curr = curr->next;}head = head->next;}curr->next = NULL;return dummy->next;
}void printList(struct ListNode* head) {while (head) {printf("%d -> ", head->val);head = head->next;}printf("NULL\n");
}void freeList(struct ListNode* head) {struct ListNode* temp;while (head) {temp = head;head = head->next;free(temp);}
}
int main() {// 创建链表 1->2->6->3->4->5->6struct ListNode* head = createNode(1);head->next = createNode(2);head->next->next = createNode(6);head->next->next->next = createNode(3);head->next->next->next->next = createNode(4);head->next->next->next->next->next = createNode(5);head->next->next->next->next->next->next = createNode(6);int val = 6;struct ListNode* newHead = removeElements(head, val);printList(newHead);freeList(newHead);return 0;
}
相关文章:

单链表的实现(数据结构)
一. 单链表的实现 我们在上一篇中简单的认识了链表的组成和结构,并打印出链表,那么今天就来具体实现一下单链表对于数据增加、删减、插入等。 接下来就是我们在链表中对于数据的增、删、插的实现,对于我们的链表来说在任何地方增加数据都需…...
印刷质量检测笔记
一、印刷质量检测的背景与挑战 印刷品的质量检测,特别是针对高精度要求的印刷产品,如包装材料、标签、书籍封面等,一直是制造业中的一个关键环节。印刷品可能存在的质量问题多种多样,包括但不限于颜色偏差、文字模糊、漏印、多印…...

16、论文阅读:Mamba YOLO:用于目标检测的基于 SSM 的 YOLO
Mamba YOLO: SSMs-Based YOLO For Object Detection 总结前言感受野为什么Transformer 的结构被引入,显著扩展了模型的感受野?状态空间模型SSM 介绍相关工作实时目标检测端到端目标检测器视觉状态空间模型 方法预处理整体架构ODSS BlockLocalSpatial Blo…...

python项目实战---使用图形化界面下载音乐
音乐下载 设计思路: 设计界面编写爬虫代码绑定爬虫打包exe文件 这个是最终的设计成果,所有的下载歌曲都在“下载mp3”文件夹里面 完整代码 逻辑代码 import os.path import reimport requests from PyQt5.QtWidgets import QApplication,QWidget,QM…...

无人机干扰与抗干扰,无人机与反制设备的矛与盾
无人机干扰与抗干扰,以及无人机与反制设备之间的关系,可以形象地比喻为矛与盾的较量。以下是对这两方面的详细探讨: 一、无人机干扰与抗干扰 1. 无人机干扰技术 无人机干扰技术是指通过各种手段对无人机系统进行干扰,使其失去正…...

JAVA基础:单元测试;注解;枚举;网络编程 (学习笔记)
单元测试 操作步骤: a.导包import org.junit; b.三个注解 Test Before After c.点击Test 运行就可以了 用在不需要控制台输入的情境下:javaweb,框架项目,微服务项目 供开发人员自己做测试。 package com.page…...
Meta 上周宣布正式开源小型语言模型 MobileLLM 系列
在 7 月发布之后,Meta 上周宣布正式开源能够在智能手机上运行的小型语言模型 MobileLLM 系列。 Meta 在四个月前发布了这两个参数量小于 10 亿的语言模型 MobileLLM 125M 及 MobileLLM 350M。如今,Meta 又开发出了更大参数量的模型版本,包括…...
安全篇(1)判断安全固件
判断安全固件的方法 一、通过串口开机打印 改方法适用Android与Tina 1.开机打印为SBOOT为安全 [289]HELLO! SBOOT is starting! 2.开机打印boot0为非安全 [88]BOOT0 commit : 1cbb5ea8b3 二、通过读数据 1.getprop | grep verifiedbootstate 这条命令的输出表示设备的…...

ArcGIS005:ArcMap常用操作101-150例动图演示
摘要:本文涵盖了GIS软件操作的多方面内容,包括地图文档的新建、打开、保存及版本兼容性处理;错误与警告的查阅及帮助文档的使用技巧;地图打印比例尺的调整与地图信息的完善;图层操作的撤销与恢复,界面元素的…...

如何用ChatGPT结合Python处理遥感数据
在科技飞速发展的时代,遥感数据的精准分析已经成为推动各行业智能决策的关键工具。从无人机监测农田到卫星数据支持气候研究,空天地遥感数据正以前所未有的方式为科研和商业带来深刻变革。然而,对于许多专业人士而言,如何高效地处…...

matlab 质心重合法实现点云配准
目录 一、算法原理1、原理概述2、参考文献二、代码实现三、结果展示1、初始位置2、配准结果本文由CSDN点云侠原创,原文链接,首发于:2024年11月5日。 一、算法原理 1、原理概述 质心重合法是将源点云 P P P...

ubuntu双屏只显示一个屏幕另一个黑屏
简洁的结论: 系统环境 ubuntu22.04 nvidia-535解决方案 删除/etc/X11/xorg.conf 文件 记录一下折腾大半天的问题。 ubuntu系统是22.04,之前使用的时候更新驱动导致桌面崩溃,重新安装桌面安装不上,请IT帮忙,IT一番操作过后也表示…...

小菜家教平台:基于SpringBoot+Vue打造一站式学习管理系统
前言 现在已经学习了很多与Java相关的知识,但是迟迟没有进行一个完整的实践(之前这个项目开发到一半,很多东西没学搁置了,同时原先的项目中也有很多的问题),所以现在准备从零开始做一个基于SpringBootVue的…...

网络自动化03:简单解释send_config_set方法并举例
目录 拓扑图设备信息 netmiko涉及方法send_config_set()方法的简单示例代码输出结果代码解释导入模块配置信息config_device_interface_description 函数主程序块总结 send_config_set方法参数:1. enter_config_mode2. config_commands3. enter_config_mode4. error…...

跳表原理笔记
课程地址 跳表是一种基于随机化的有序数据结构,它提出是为了赋予有序单链表以 O(logn) 的快速查找和插入的能力 创建 首先在头部创建一个 sentinel 节点,然后在 L1 层采用“抛硬币”的方式来决定 L0 层的指针是否增长到 L1 层 例如上图中,L…...

计算机毕业设计Hadoop+PySpark深度学习游戏推荐系统 游戏可视化 游戏数据分析 游戏爬虫 Scrapy 机器学习 人工智能 大数据毕设
温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 作者简介:Java领…...
AI开发-三方库-torch-torchvision
1 需求 数据集:torchvision.datasets torchvision.datasets.MNIST数据变换:torchvision.transforms torchvision.transforms.Composetorchvision.transforms.ToTensortorchvision.transforms.Normalize模型:torchvision.models可视化工具&…...
解析 MySQL 数据库容量统计、存储限制与优化技巧
管理 MySQL 数据库时,了解数据库中的数据量和存储占用情况是非常重要的,尤其是在面对大规模数据时。无论是为了优化数据库性能,还是为了进行容量规划,准确地统计数据库的容量可以帮助我们做出更好的决策。mysql的客户端工具是Navi…...
智能工厂的软件设计 思维进阶与数学程序
本文要点 讨论 “智能工厂的软件设计”中的“数学程序”。 这里 “数学程序” 是指能“格物致知”来理解“相续”一词。 完整的表述是: 思想素养提升的 思维进阶法(三种 数学程序 : 格物致知 )之思维导图: 二叉树及其…...
技术速递|GitHub Copilot upgrade assistant for Java 技术预览发布!
作者:Nick Zhu - Senior Program Manager 排版:Alan Wang 随着人工智能和大型语言模型(LLMs)的不断发展,Agent(“智能代理”)和智能代理化工作流程正在迅速成为AI领域的下一个前沿。这些自主系统…...

7.4.分块查找
一.分块查找的算法思想: 1.实例: 以上述图片的顺序表为例, 该顺序表的数据元素从整体来看是乱序的,但如果把这些数据元素分成一块一块的小区间, 第一个区间[0,1]索引上的数据元素都是小于等于10的, 第二…...

智慧医疗能源事业线深度画像分析(上)
引言 医疗行业作为现代社会的关键基础设施,其能源消耗与环境影响正日益受到关注。随着全球"双碳"目标的推进和可持续发展理念的深入,智慧医疗能源事业线应运而生,致力于通过创新技术与管理方案,重构医疗领域的能源使用模式。这一事业线融合了能源管理、可持续发…...

8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂
蛋白质结合剂(如抗体、抑制肽)在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上,高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术,但这类方法普遍面临资源消耗巨大、研发周期冗长…...

理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端
🌟 什么是 MCP? 模型控制协议 (MCP) 是一种创新的协议,旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议,它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...

iPhone密码忘记了办?iPhoneUnlocker,iPhone解锁工具Aiseesoft iPhone Unlocker 高级注册版分享
平时用 iPhone 的时候,难免会碰到解锁的麻烦事。比如密码忘了、人脸识别 / 指纹识别突然不灵,或者买了二手 iPhone 却被原来的 iCloud 账号锁住,这时候就需要靠谱的解锁工具来帮忙了。Aiseesoft iPhone Unlocker 就是专门解决这些问题的软件&…...

蓝牙 BLE 扫描面试题大全(2):进阶面试题与实战演练
前文覆盖了 BLE 扫描的基础概念与经典问题蓝牙 BLE 扫描面试题大全(1):从基础到实战的深度解析-CSDN博客,但实际面试中,企业更关注候选人对复杂场景的应对能力(如多设备并发扫描、低功耗与高发现率的平衡)和前沿技术的…...

计算机基础知识解析:从应用到架构的全面拆解
目录 前言 1、 计算机的应用领域:无处不在的数字助手 2、 计算机的进化史:从算盘到量子计算 3、计算机的分类:不止 “台式机和笔记本” 4、计算机的组件:硬件与软件的协同 4.1 硬件:五大核心部件 4.2 软件&#…...
Kubernetes 网络模型深度解析:Pod IP 与 Service 的负载均衡机制,Service到底是什么?
Pod IP 的本质与特性 Pod IP 的定位 纯端点地址:Pod IP 是分配给 Pod 网络命名空间的真实 IP 地址(如 10.244.1.2)无特殊名称:在 Kubernetes 中,它通常被称为 “Pod IP” 或 “容器 IP”生命周期:与 Pod …...

数据结构第5章:树和二叉树完全指南(自整理详细图文笔记)
名人说:莫道桑榆晚,为霞尚满天。——刘禹锡(刘梦得,诗豪) 原创笔记:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 上一篇:《数据结构第4章 数组和广义表》…...

RushDB开源程序 是现代应用程序和 AI 的即时数据库。建立在 Neo4j 之上
一、软件介绍 文末提供程序和源码下载 RushDB 改变了您处理图形数据的方式 — 不需要 Schema,不需要复杂的查询,只需推送数据即可。 二、Key Features ✨ 主要特点 Instant Setup: Be productive in seconds, not days 即时设置 :在几秒钟…...