数据结构——单链表实现和注释浅解

关于单链表的基础部分增删查改的实现和一点理解,写在注释里~ 


 


 SList.h

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>//定义节点的结构
//数据 + 指向下一个节点的指针
typedef int SLTDataType;typedef struct SListNode
{SLTDataType data;//当前节点存储的数据struct SListNode* next;//指向下一个节点的指针
}SLTNode;//打印
void SLTPrint(SLTNode* phead);//申请节点
SLTNode* SLTBuyNode(SLTDataType x);//尾插
void SLTPushBack(SLTNode** pphead, SLTDataType x);
//头插
void SLTPushFront(SLTNode** pphead, SLTDataType x);
//尾删
void SLTPopBack(SLTNode** pphead);
//头删
void SLTPopFront(SLTNode** pphead);//查找
SLTNode* SLTFind(SLTNode* phead, SLTDataType x);//在指定位置之前插入数据
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x);
//在指定位置之后插入数据
void SLTInsertAfter(SLTNode* pos, SLTDataType x);//删除pos节点
void SLTErase(SLTNode** pphead, SLTNode* pos);
//删除pos之后的节点
void SLTEraseAfter(SLTNode* pos);//销毁链表
void SListDesTroy(SLTNode** pphead);


  SList.c

#include"SList.h"//只要形参变了而实参没有变化,那么就什么传的是值,而不是地址//data:节点存储的数据
//next:指向下一个节点的指针//打印
void SLTPrint(SLTNode* phead)
{//创建一个临时变量pcur将头节点的值赋予给pcur//pcur指向当前节点的值SLTNode* pcur = phead;//判断pcur是否为空while (pcur){//打印指向当前节点存储的数据printf("%d->", pcur->data);//将pucr指向的下一个节点指针的地址赋予给pcurpcur = pcur->next;}//当pcur为空时则打印NULLprintf("NULL\n");
}//申请节点
SLTNode* SLTBuyNode(SLTDataType x)
{SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));if (newnode == NULL){perror("malloc fail!");exit(1);}newnode->data = x;newnode->next = NULL;return newnode;
}//尾插
// 只要形参变了而实参没有变化,那么就什么传的是值,而不是地址
//要先找到尾节点,再把尾节点的next指针指向新节点(newnode)
void SLTPushBack(SLTNode** pphead, SLTDataType x)
{assert(pphead);//*pphead 就是指向第一个节点的指针//申请一个新节点SLTNode* newnode = SLTBuyNode(x);//如果为空链表if (*pphead == NULL){*pphead = newnode;}else//非空链表{//找尾节点//定义一个尾节点,链表刚开始头节点和尾节点在同一个位置SLTNode* ptail = *pphead;//*pphead一级指针,指向第一个节点的指针//判断当尾节点指针指向的下一个位置为NULL结束//当ptail指针指向的下一个位置不为NULL时,ptail继续运行while (ptail->next){//把ptail指针指向的下一个位置的指针地址赋予ptailptail = ptail->next;}//当ptail指针指向的下一个位置为NULL时,ptail指向的就是尾结点//将ptail的next指针指向新节点ptail->next = newnode;}}//头插
void SLTPushFront(SLTNode** pphead, SLTDataType x)
{assert(pphead);//申请一个新节点SLTNode* newnode = SLTBuyNode(x);//*pphead一级指针,指向第一个节点的指针//将新节点的next指针指向*pphead (头节点)newnode->next = *pphead;//然后再把新节点变成新的头节点*pphead*pphead = newnode;
}//尾删
void SLTPopBack(SLTNode** pphead)
{//链表不能为空assert(pphead && *pphead);//如果链表只有一个节点if ((*pphead)->next == NULL) // -> 优先级高于*{free(*pphead);*pphead = NULL;}else//如果链表有多个节点{//定义一个函数prev(前一个)//将prev和ptail都指向头节点 *ppheadSLTNode* prev = *pphead;SLTNode* ptail = *pphead;//判断ptail的next指针是否为空while (ptail->next){//将prev指向ptail的位置,ptail指向ptail的next指针的位置prev = ptail;ptail = ptail->next;}//如果ptail的next指针不为空,则把ptail free掉free(ptail);//将ptail和prev的next指针置为空ptail = NULL;prev->next = NULL;}
}//头删
void SLTPopFront(SLTNode** pphead)
{//链表不能为空assert(pphead && *pphead);//定义一个next指针,将头节点的next指针指向第二个节点(next)//用来保存第二个节点的位置SLTNode* next = (*pphead)->next;//释放头节点free(*pphead);//将第二个节点变成新的头节点*pphead = next;
}//查找
SLTNode* SLTFind(SLTNode* phead, SLTDataType x)
{//定义一个指针pcur指向头节点//这里不论pcur怎么变化都不会影响pheadSLTNode* pcur = phead;//while循环遍历while (pcur){//判断当前节点存储的数据是否与要查找的值相同if (pcur->data == x){//如果是就返回pcurreturn pcur;}//不是pcur就指向pcur的next指针继续走pcur = pcur->next;}//如果结束循环还没有找到就返回NULLreturn NULL;
}//在指定位置之  前  插入数据  prev:上一个
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x)
{//链表不能为空assert(pphead && *pphead);assert(pos);//插入之前要先申请新节点SLTNode* newnode = SLTBuyNode(x);若pos == *pphead;说明是头插if (pos == *pphead){SLTPushFront(pphead, x);}else//不是头插{//先找到pos的前一个节点//定义一个函数prev,指向头节点SLTNode* prev = *pphead;//如果prev的下一个指针指向的  不是  pos则进行循环while (prev->next != pos){//不是prev就指向prev的next指针继续走prev = prev->data;}//找到之后//prev->newnode->pos//先将newnode的next指针指向pos,再把prev的next指针指向指向newnodenewnode->next = pos;prev->next = newnode;}}//在指定位置之  后  插入数据
void SLTInsertAfter(SLTNode* pos, SLTDataType x)
{assert(pos);SLTNode* newnode = SLTBuyNode(x);//pos -> newnode -> pos->next//先将newnode的next指针指向pos的下一个节点(next),再把pos的next指针指向newnodenewnode->next = pos->next;pos->next = newnode;
}//删除pos节点
void SLTErase(SLTNode** pphead, SLTNode* pos)
{assert(pphead && *pphead);assert(pos);//pos是头结点if (pos == *pphead){//头删SLTPopFront(pphead);}else//pos不是头结点{SLTNode* prev = *pphead;while (prev->next != pos){prev = prev->next;}//prev pos pos->next//要先把prev的下一个指针指向pos的下一个指针指向的位置再释放掉pos// 防止找不到pos的下一个指针指向的位置prev->next = pos->next;free(pos);pos = NULL;}
}//删除pos之后的节点
void SLTEraseAfter(SLTNode* pos)
{assert(pos && pos->next);//定义一个临时指针del,将pos的next指针存放到del中SLTNode* del = pos->next;//把pos的next指针指向del的next指针//pos del del->nextpos->next = del->next;free(del);del = NULL;
}//销毁链表
void SListDesTroy(SLTNode** pphead)
{assert(pphead && *pphead);SLTNode* pcur = *pphead;while (pcur){SLTNode* next = pcur->next;free(pcur);pcur = next;}//pcur*pphead = NULL;
}


Test.c 

#include"SList.h"void SListTest01()
{//链表是由一个一个的节点组成//创建几个节点SLTNode* node1 = (SLTNode*)malloc(sizeof(SLTNode));node1->data = 1;SLTNode* node2 = (SLTNode*)malloc(sizeof(SLTNode));node2->data = 2;SLTNode* node3 = (SLTNode*)malloc(sizeof(SLTNode));node3->data = 3;SLTNode* node4 = (SLTNode*)malloc(sizeof(SLTNode));node4->data = 4;//将四个节点连接起来node1->next = node2;node2->next = node3;node3->next = node4;node4->next = NULL;//调用链表的打印SLTNode* plist = node1;SLTPrint(plist);
}void SListTest02()
{SLTNode* plist = NULL;SLTPushBack(&plist, 1);SLTPushBack(&plist, 2);SLTPushBack(&plist, 3);SLTPushBack(&plist, 4);SLTPrint(plist); // 1->2->3->4->NULLSListDesTroy(&plist);SLTPrint(plist);//测试查找//SLTNode* find = SLTFind(plist, 1);//SLTInsert(&plist, find, 11);//SLTInsertAfter(find, 11);//删除pos节点//SLTErase(&plist, find);//SLTEraseAfter(find);//SLTPrint(plist);//if (find == NULL)//{//	printf("没有找到!\n");//}//else {//	printf("找到了!\n");//}//SLTPushBack(NULL, 5);////测试头插//SLTPushFront(&plist, 6);//SLTPrint(plist);//SLTPushFront(&plist, 7);//SLTPrint(plist);//SLTPushFront(&plist, 8);//SLTPrint(plist);//测试头删//SLTPopFront(&plist);//SLTPrint(plist);// 2->3->4->NULL//SLTPopFront(&plist);//SLTPrint(plist);//SLTPopFront(&plist);//SLTPrint(plist);//SLTPopFront(&plist);//SLTPrint(plist);//SLTPopFront(&plist);//SLTPrint(plist);}int main()
{//SListTest01();SListTest02();return 0;
}

 


一点浅解,感谢观看~

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

如何限制与管控员工上网行为?五个管控方法让员工效率倍增!

在现代企业中&#xff0c;互联网是工作中不可或缺的工具&#xff0c;但与此同时&#xff0c;员工在工作时间浏览与工作无关的网站、进行网络娱乐等行为&#xff0c;也成为了影响企业生产力和效率的主要因素之一。如何有效限制和管控员工的上网行为&#xff0c;从而提升工作效率…

解决ubuntu系统无法与FinalShell无法连接问题

问题 解决方案 先下载ubuntu网络工具 sudo apt install net-tools输入密码 下载完成后进入管理员模式查看密码 sudo -ihostname -I查看IP 得到ip地址后再继续安装 openssh-server 插件 sudo apt-get install openssh-server问题解决 尝试连接FinalShell

跨系统环境下LabVIEW程序稳定运行

在LabVIEW开发中&#xff0c;不同电脑的配置和操作系统&#xff08;如Win11与Win7&#xff09;可能对程序的稳定运行产生影响。为了确保程序在不同平台上都能正常且稳定运行&#xff0c;需要从兼容性、驱动、以及性能优化等多个方面入手。本文将详细介绍如何在不同系统环境下&a…

每日OJ_牛客_骆驼命名法(递归深搜)

目录 牛客_骆驼命名法&#xff08;简单模拟&#xff09; 解析代码 牛客_骆驼命名法&#xff08;简单模拟&#xff09; 骆驼命名法__牛客网 解析代码 首先一个字符一个字符的读取内容&#xff1a; 遇到 _ 就直接跳过。如果上一个字符是 _ 则下一个字符转大写字母。 #inclu…

从0开始深度学习(4)——线性回归概念

1 线性回归 回归&#xff08;regression&#xff09;指能为一个或多个自变量与因变量之间的关系进行建模。 1.1 线性模型 线性假设是指目标可以表示为特征的加权和&#xff0c;以房价和面积、房龄为例&#xff0c;可以有下面的式子&#xff1a; w称为权重&#xff08;weigh…

Centos7.9部署Gitlab-ce-16.9

一、环境信息 软件/系统名称版本下载地址备注Centos77.9.2009https://mirrors.nju.edu.cn/centos/7.9.2009/isos/x86_64/CentOS-7-x86_64-DVD-2009.isogitlab-cegitlab-ce-16.9.1https://mirror.tuna.tsinghua.edu.cn/gitlab-ce/yum/el7/gitlab-ce-16.9.1-ce.0.el7.x86_64.rpm…

磁电偶极子天线学习1 一种60GHz 宽带圆极化口径耦合磁电偶极子天线阵列

摘要&#xff1a; 一种新型的圆极化口径耦合天线被提出。这种圆极化磁电偶极子天线由刻蚀在短路基片集成波导的一部分的宽臂上&#xff0c;并且很容易被集成基片。在工作频段内实现了宽于28.8%的阻抗带宽和宽带3-dB的25.9%的轴比和的增益。此外&#xff0c;因为圆极化辐射由两个…

win11如何录屏

在 Win11 中录屏可以使用系统自带的工具和一些第三方应用。以下是几种方法&#xff1a; 方法一&#xff1a;使用 Xbox Game Bar 1. 打开 Xbox Game Bar - 按 Win G 组合键打开 Xbox Game Bar。 2. 开始录制 - 在显示的界面中&#xff0c;点击“录制”按钮&#xff08;…

C++入门(06)安装QT并快速测试体验一个简单的C++GUI项目

文章目录 1. 清华镜像源下载2. 安装3. 开始菜单上的 QT 工具4. 打开 Qt Creator5. 简单的 GUI C 项目5.1 打开 Qt Creator 并创建新项目5.2 设计界面5.3 添加按钮的点击事件5.4 编译并运行项目 6. 信号和槽&#xff08;Signals and Slots&#xff09; 这里用到了C类与对象的很多…

知名AIGC人工智能专家培训讲师唐兴通谈AI大模型数字化转型数字新媒体营销与数字化销售

在过去的二十年里&#xff0c;中国企业在数字营销领域经历了一场惊心动魄的变革。从最初的懵懂无知到如今的游刃有余&#xff0c;这一路走来&#xff0c;既有模仿学习的艰辛&#xff0c;也有创新突破的喜悦。然而&#xff0c;站在人工智能时代的门槛上&#xff0c;我们不禁要问…

认知杂谈53

今天分享 有人说的一段争议性的话 I I 1.自助者天助 首先呢&#xff0c;咱得好好琢磨琢磨“自助者天助”这句话。这话说起来好像有点高深莫测的感觉&#xff0c;其实啊&#xff0c;道理特别简单。 就是说要是你自己都不乐意努力&#xff0c;那老天爷也不会平白无故地来帮你…

【Map】、集合总结

Map(*)——映射 比较之前的集合 List 为什么使用map <k,v>&#xff1a;key–value Api–>尽量用k去操作value put<k,v> package com.ffyc.map;import java.util.HashMap; import java.util.Map;/*** 映射*/ public class MapDemo {public static void main(St…

1 模拟——67. 二进制求和

1 模拟 67. 二进制求和 给你两个二进制字符串 a 和 b &#xff0c;以二进制字符串的形式返回它们的和。 示例 1&#xff1a; 输入:a "11", b "1" 输出&#xff1a;"100" 示例 2&#xff1a; 输入&#xff1a;a "1010", b "…

6.3图的遍历

图的遍历是指从某点出发,按照某种搜索方式沿着边访问图中所有节点 图的遍历算法主要有两种:广度优先,深度优先 都需要辅助数组visited[]来记录节点是否被访问过 6.3.1广度优先搜索 like层次遍历,需要辅助队列 代码实现 #include<stdio.h> #define maxnum 15 bool vi…

PMP–一、二、三模–分类–14.敏捷–技巧–看板面板与燃尽图燃起图

文章目录 技巧一模14.敏捷--方法--看板&#xff08;类似卡片&#xff09;1、 [单选] 根据项目的特点&#xff0c;项目经理建议选择一种敏捷方法&#xff0c;该方法限制团队成员在任何给定时间执行的任务数。此方法还允许团队提高工作过程中问题和瓶颈的可见性。项目经理建议采用…

【国赛急救包】数模国赛查重规则及降重技巧

国赛已经快接近尾声了&#xff0c;各位宝宝论文写得怎么样啦~ 今天为大家分享关于国赛查重的一些规则&#xff0c;以及降重技巧&#xff01;快收藏起来吧~ 1. 国赛查重要求及如何查重 • 数学建模国赛的查重除了知网数据库以外&#xff0c;更重要的是自建库的查重比对&#x…

vLLM (4) - LLMEngine上篇

系列文章目录 vLLM (1) - Qwen2推理&部署 vLLM (2) - 架构总览 vLLM (3) - Sequence & SequenceGroup vLLM (4) - LLMEngine上篇 vLLM (5) - LLMEngine下篇 文章目录 系列文章目录前言一、类图二、LLM三、LLMEngine四、GPUExectuor五、Worker六、ModelRunner七、Cache…

windows下使用vscode编写运行以及调试C/C++

vscode支持类似于vs的断点调试c/c&#xff0c;也可以直接编译&运行c/c 先是编译运行 c/c的方法 微软官方起初设定的科学做法(这也是现在的科学做法)是通过在vscode集成控制台写命令行的方式来实现编译运行程序的,但也可以通过code runner插件…

软件工程-图书管理系统的概要设计

软件概要设计说明书 目录 软件概要设计说明书 一、引言 1.1 编写目的 1.2 背景 1.3 定义 1.3.1特定对象 1.3.2专业术语 1.4 参考资料 二、总体设计 2.1 需求规定 2.1.1信息要求 2.1.2功能要求 2.2 运行环境 2.3 基本概要设计和处理流程 2.4 体系结构设计 2.5 模…

网络安全运维培训一般多少钱

在当今数字化时代&#xff0c;网络安全已成为企业和个人关注的焦点。而网络安全运维作为保障网络安全的重要环节&#xff0c;其专业人才的需求也日益增长。许多人都对网络安全运维培训感兴趣&#xff0c;那么&#xff0c;网络安全运维培训一般多少钱呢? 一、影响网络安全运维培…