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

【数据结构初阶】单链表

目录

  • 一、思路
  • >>>>>>>>>>>>过程<<<<<<<<<<<<<<<
  • 1.打印
  • 2.尾插
  • 3.尾删
  • 4.头插
  • 5.头删
  • 6.查找
  • 7.指定位置后插入
  • 8.指定位置后删除
  • 9.链表的销毁
  • 二、整个程序
  • 1.SLTlist.c
  • 2.SLTlist.c

一、思路

#define _CRT_SECURE_NO_WARNINGS 1#include<stdio.h>
#include<stdlib.h>
#include<assert.h>typedef int SLTdataType;typedef struct SLTNodelist
{SLTdataType data;struct SLTNodelist* next;
}SLTNode;//打印
void SLTPrint(SLTNode* phead);
//尾插
void SLTAddBack(SLTNode** pphead, SLTdataType x);
//尾删
void SLTDelBack(SLTNode** pphead);
//头插
void SLTAddPop(SLTNode** pphead, SLTdataType x);
//头删
void SLTDelPop(SLTNode** pphead);
//查找
SLTNode* SLTFindlist(SLTNode* phead, SLTdataType x);
//指定位置后插入
void SLTAddPoint(SLTNode** pphead, SLTNode* pos, SLTdataType x);
//指定位置后删除
void SLDelPoint(SLTNode** pphead, SLTNode* pos);
//链表的销毁
void SLTDestroy(SLTNode** pphead);

>>>>>>>>>>>>过程<<<<<<<<<<<<<<<

1.打印

void PrintfSTLlist(SLTNode*phead)
{STLNode*cur=phead;while(cur){printf("%d->\n",cur->Data);cur=cur->next;}printf("NULL\n");}

1.这个打印函数需要断言吗?
不需要,即使结构体为空,也能打印,只不过是没有数据而已,这是打印出来的就是空的。如果能打印出来,但是却断言报错,不太合适。

2.怎么打印?
用一个指针cur指向结构体,用while循环打印出来,当cur指向的结构体为空时,停止打印。

3.while的判断条件可以是while(cur->next)吗?
不可以,因为这样最后一个的数据就打印不出来了。

4.在while循环中,让cur指向下一个结构体,可以用cur++吗?
不可以,不同于顺序表,顺序表的数据是存储在一个连续的空间里的,链表它是链接起来的结构体地址。

2.尾插

SLTNode*Buynewnode(SLTDataTap x)
{SLTNode*newnode=(SLTNode*)malloc(sizeof(SLTNode));if(newnode==NULL){perror("malloc failed");return NULL;}newnode->Data=x;newnode->next=NULL;return newnode;
}
void SLTAddPop(SLTNode**pphead,SLTDataTap x)
{//开辟空间SLTNode*newnode=Buynewnode(x);if(newnode==NULL){return;}//找尾//情况一:pphead为空if(*pphead==NULL){*pphead=newnode;}//情况二:pphead不为空SLTNode*tail=pphead;else{while(tail->next){tail=tail->next;}tail->next=newnode;}
}

1.为什么void SLTAddPop(SLTNode**pphead,SLTDataTap)这不能用一级指针接收?

2.怎么进行尾插?
在插入一个数据之前,首先得为这个结构体开辟一个结点,用malloc开辟,由于插入数据时我们都要进行开辟一个结的操作,所以我们可以打包成一个函数SLTNode*Buynewnode(SLTDataTap x)
进行尾插那么就是要找到尾,找尾分两种情况:1. 当*pphead本身为空时,就直接将newnode插入就可以了;2. *pphead本身不为空时,只要找到tail->next为空的,那个就是结构体的尾了
在这里插入图片描述

3.当pphead不为空时,找尾while循环的判断条件可以写成这样tail!=NULL与插入结点时tail=newnode吗?
不可以,因为这样就无法保持链接状态了。

3.尾删

void SLTDelBack(SLTNode**pphead)
{assert(*pphead);//情况一:只有一个数据if((*pphead)->next==NULL){free(*pphead);*pphead=NULL;}//情况二:不止一个数据SLTNode*tail=*pphead;SLTNode*pre=*pphead;while(tail->next){pre=tail;tail=tail->next;}free(tail);tail=NULL;pre->next=NULL;
}

1.尾删需要断言吗?
需要,因为如果链表为空,是删不了的;
2.尾删的思路
尾删分三种讨论:

1.如果链表为空,删不了,我们这里断言判断一下
2.链表中只有一个数据
3.链表中的数据为一个以上

4.头插

void SLTAddPop(SLTNode** pphead, SLTdataType x)
{assert(pphead);SLTNode* newnode = Buynewnode(x);if (newnode == NULL){return;}newnode->next = *pphead;*pphead = newnode;
}

1.头插需要断言吗?
因为pphead永远不能为空,所以要断言;但是当链表为空的时候,可以插入数据,*pphead是不需要断言的。
2.头插的思路
首先先要创建一个结点,将结点的next与链表的第一个指针链接起来。最后要注意把链表的头给改成newnode。

5.头删

void SLTDelPop(SLTNode** pphead)
{assert(pphead);assert(*pphead);SLTNode* cur = *pphead;*pphead = cur->next;free(cur);cur = NULL;
}

1.头删需要断言吗?
因为pphead永远不能为空,所以要断言;且空链表不能删除,所以*pphead也需要断言。
2.头删的思路
在这里插入图片描述

6.查找

SLTNode* SLTFindlist(SLTNode* phead, SLTdataType x)
{SLTNode* cur = phead;while (cur){if (cur->data == x){return cur;}cur = cur->next;}return NULL;
}

1.查找需要断言吗?
不需要,链表为空就返回NULL;
2.查找的思路
当链表的cur不为空,就继续逐一比对,找到了就返回cur,没找到就指向下一个;直到cur指向空,如果还没找到,就返回NULL;

7.指定位置后插入

void SLTAddPoint(SLTNode** pphead, SLTNode* pos, SLTdataType x)
{assert(pos);assert(pphead);SLTNode* newnode = Buynewnode(x);if (newnode == NULL){return;}//newnode->next = pos->next;pos->next = newnode;}

1.需要断言吗?
因为pphead永远不能为空,所以要断言;指定的位置pos不能为空,所以需要断言;
2.思路
创建一个新结点newnode,然后先让newnode->next = pos->next;让newnode的后面链接起来,在让pos和newnode链接起来pos->next = newnode;;反过来写的话,由于pos->next已经被改了,所以不能是pos与newnode链接,插入就会失败;

8.指定位置后删除

void SLDelPoint(SLTNode** pphead, SLTNode* pos)
{assert(pos);assert(pphead);assert(*pphead);if ((*pphead)->next == NULL&&pos->next==NULL){return;}else{SLTNode* cur = pos->next;pos->next = cur->next;free(cur);cur = NULL;}
}

1.需要断言吗?
因为pphead永远不能为空,所以要断言;因为如果链表为空,是删不了的,所以*phead需要断言,指定的位置pos不能为空,所以需要断言;

9.链表的销毁

void SLTDestroy(SLTNode** pphead)
{assert(pphead);assert(*pphead);SLTNode* cur = *pphead;SLTNode* pre = cur;while (cur){pre = cur->next;free(cur);cur = pre;}*pphead = cur;
}

2.思路
结点逐一free,最后记得把*pphead改为最后的cur。

二、整个程序

1.SLTlist.c

#define _CRT_SECURE_NO_WARNINGS 1#include<stdio.h>
#include<stdlib.h>
#include<assert.h>typedef int SLTdataType;typedef struct SLTNodelist
{SLTdataType data;struct SLTNodelist* next;
}SLTNode;//打印
void SLTPrint(SLTNode* phead);
//尾插
void SLTAddBack(SLTNode** pphead, SLTdataType x);
//尾删
void SLTDelBack(SLTNode** pphead);
//头插
void SLTAddPop(SLTNode** pphead, SLTdataType x);
//头删
void SLTDelPop(SLTNode** pphead);
//查找
SLTNode* SLTFindlist(SLTNode* phead, SLTdataType x);
//指定位置后插入
void SLTAddPoint(SLTNode** pphead, SLTNode* pos, SLTdataType x);
//指定位置后删除
void SLDelPoint(SLTNode** pphead, SLTNode* pos);
//链表的销毁
void SLTDestroy(SLTNode** pphead);

2.SLTlist.c

#define _CRT_SECURE_NO_WARNINGS 1#include"SLTlist.h"void SLTPrint(SLTNode* phead)
{SLTNode* cur = phead;while (cur){printf("%d->", cur->data);cur = cur->next;}printf("NULL\n");
}SLTNode* Buynewnode(SLTdataType x)
{SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));if (newnode == NULL){return NULL;}newnode->data = x;newnode->next = NULL;return newnode;
}void SLTAddBack(SLTNode** pphead, SLTdataType x)
{assert(pphead);SLTNode* newnode = Buynewnode(x);if (newnode == NULL){return;}//情况1:pphead为空if (*pphead == NULL){*pphead = newnode;}//情况2:pphead不为空//找尾else{SLTNode* tail = *pphead;while (tail->next){tail = tail->next;}tail->next = newnode;}
}void SLTDelBack(SLTNode** pphead)
{assert(pphead);assert(*pphead);//情况1:链表中只有一个节点if ((*pphead)->next == NULL){free(*pphead);*pphead = NULL;}//情况2:链表中只有一个节点else{SLTNode* tail = *pphead;while (tail->next->next){tail = tail->next;}SLTNode* pre = tail->next;free(pre);tail->next = NULL;}}void SLTAddPop(SLTNode** pphead, SLTdataType x)
{assert(pphead);SLTNode* newnode = Buynewnode(x);if (newnode == NULL){return;}newnode->next = *pphead;*pphead = newnode;
}void SLTDelPop(SLTNode** pphead)
{assert(pphead);assert(*pphead);SLTNode* cur = *pphead;*pphead = cur->next;free(cur);cur = NULL;
}SLTNode* SLTFindlist(SLTNode* phead, SLTdataType x)
{SLTNode* cur = phead;while (cur){if (cur->data == x){return cur;}cur = cur->next;}return NULL;
}void SLTAddPoint(SLTNode** pphead, SLTNode* pos, SLTdataType x)
{assert(pos);assert(pphead);SLTNode* newnode = Buynewnode(x);if (newnode == NULL){return;}//newnode->next = pos->next;pos->next = newnode;}void SLDelPoint(SLTNode** pphead, SLTNode* pos)
{assert(pos);assert(pphead);assert(*pphead);if ((*pphead)->next == NULL&&pos->next==NULL){return;}else{SLTNode* cur = pos->next;pos->next = cur->next;free(cur);cur = NULL;}
}void SLTDestroy(SLTNode** pphead)
{assert(pphead);assert(*pphead);SLTNode* cur = *pphead;SLTNode* pre = cur;while (cur){pre = cur->next;free(cur);cur = pre;}*pphead = cur;
}

相关文章:

【数据结构初阶】单链表

目录一、思路>>>>>>>>>>>>过程<<<<<<<<<<<<<<<1.打印2.尾插3.尾删4.头插5.头删6.查找7.指定位置后插入8.指定位置后删除9.链表的销毁二、整个程序1.SLTlist.c2.SLTlist.c一、思路 #define …...

多线程代码案例-阻塞队列

hi,大家好,今天为大家带来多线程案例--阻塞队列 这块知识点也很重要,要好好掌握呀~~~ &#x1f338;&#x1f338;&#x1f338;&#x1f338;&#x1f338;&#x1f338;&#x1f338;&#x1f338;&#x1f338;&#x1f338;&#x1f338;&#x1f338;&#x1f338;&#x…...

mysql的limit查询竟然有坑?

背景 最近项目联调的时候发现了分页查询的一个bug&#xff0c;分页查询总有数据查不出来或者重复查出。 数据库一共14条记录。 如果按照一页10条。那么第一页和第二页的查询SQL和和结果如下。 .png) 那么问题来了&#xff0c;查询第一页和第二页的时候都出现了11,12,13的记录…...

【Docker】MAC电脑下的Docker操作

文章目录安装Docker部署mysql 一主一从登录ChatGPT搞方案本地创建一个文件夹编辑docker-compose.yml文件启动检查并编排容器验证基于command的my.cnf配置的加载主数据库建一个用户给子数据库用于主从复制启动主从同步安装Docker 官网地址 https://www.docker.com/ 下载安装 验…...

【Python3】matplotlib,模块,进/线程,文件/xml,百度人脸api,hal/aiohttp/curl

文章目录1.matplotlib/时间复杂度/线性表&#xff1a;顺序表要求存储空间必须连续2.python模块导入&#xff1a;python3 -c ‘import sys;print(sys.path)’ 显示导入模块时会去哪些路径下查找3.进/线程&#xff1a;进/线程是不能随便创建&#xff0c;就像每招一个员工是有代价…...

异或相关算法

文章目录1. 异或的性质2. 题目一3. 题目二4. 题目三5. 题目四1. 异或的性质 我们知道&#xff0c;异或的定义是&#xff1a;相同为0&#xff0c;相异为1。所以也被称为无进位相加&#xff0c;根据这定义&#xff0c;我们可以得出三个性质&#xff1a; 1. N ^ N0。2. N ^ 0N。3…...

python 使用pyshp读写shp文件

安装 pip install pyshp 引入 import shapefile读取 sfshapefile.Reader("{路径名}",encodingutf-8) # 仅仅读取 shapes与shape shapessf.shapes() 返回值是一个列表&#xff0c;包含该文件中所有的”几何数据”对象shapesf.shape(0) Shape是第1个”几何数据”…...

eNSP FTP基础配置实验

关于本实验在本实验中&#xff0c;我们通过两台路由器来展示通过FTP在两台路由器之间传输文件。其中一台路由器AR2作为FTP服务器&#xff0c;另一台路由器AR1以FTP的方式登录AR2&#xff0c;并对AR2的文件系统进行一些更改。实验目的熟悉华为网络设备文件系统的管理。掌握华为网…...

堆及其多种接口与堆排序的实现

我们本期来讲解堆结构 目录 堆的结构 堆的初始化 堆的销毁 堆的插入 向上调整算法 堆的删除 向下调整算法 取堆顶元素 判断堆是否为空 堆中元素个数 堆排序 向下调整与向上调整效率计算 Top-K问题 全部代码 堆的结构 堆是一种用数组模拟二叉树的结构 逻辑结构是…...

JNI原理及常用方法概述

1.1 JNI(Java Native Interface) 提供一种Java字节码调用C/C的解决方案&#xff0c;JNI描述的是一种技术。 1.2 NDK(Native Development Kit) Android NDK 是一组允许您将 C 或 C&#xff08;“原生代码”&#xff09;嵌入到 Android 应用中的工具&#xff0c;NDK描述的是工具集…...

【Docker】之docker-compose的介绍与命令的使用

&#x1f341;博主简介 &#x1f3c5;云计算领域优质创作者   &#x1f3c5;华为云开发者社区专家博主   &#x1f3c5;阿里云开发者社区专家博主 &#x1f48a;交流社区&#xff1a;运维交流社区 欢迎大家的加入&#xff01; 文章目录docker-compose简介docker-compose基础…...

水果新鲜程度检测系统(UI界面+YOLOv5+训练数据集)

摘要&#xff1a;水果新鲜程度检测软件用于检测水果新鲜程度&#xff0c;利用深度学习技术识别腐败或损坏的水果&#xff0c;以辅助挑拣出新鲜水果&#xff0c;支持实时在线检测。本文详细介绍水果新鲜程度检测系统&#xff0c;在介绍算法原理的同时&#xff0c;给出Python的实…...

flask多并发

多线程 flask默认使用多进程处理请求&#xff0c;因此&#xff0c;是支持并发的。比如两个调用a.html和b.html&#xff0c; 请求a.html未运行完成&#xff0c;在浏览访问b.html不会阻塞。开两个不同浏览器&#xff0c;分别请求请求运行时间较长的a.html也不阻塞。只要不用一个…...

我用Python django开发了一个商城系统,已开源,求关注!

起始 2022年我用django开发了一个商城的第三方包&#xff0c;起名为&#xff1a;django-happy-shop。当时纯粹是利用业余时间来开发和维护这个包&#xff0c;想法也比较简单&#xff0c;Python语言做web可能用的人比较少&#xff0c;不一定有多少人去关注&#xff0c;就当是一个…...

大数据项目之数仓相关知识

第1章 数据仓库概念 数据仓库&#xff08;DW&#xff09;: 为企业指定决策&#xff0c;提供数据支持的&#xff0c;帮助企业&#xff0c;改进业务流程&#xff0c;提高产品质量等。 DW的输入数据通常包括&#xff1a;业务数据&#xff0c;用户行为数据和爬虫数据等 ODS: 数据…...

RK3588平台开发系列讲解(视频篇)RTP H264 码流打包详解

平台内核版本安卓版本RK3588Linux 5.10Android 12文章目录 一、单 NALU 封包方式二、组合封包方式三、分片封包方式沉淀、分享、成长,让自己和他人都能有所收获!😄 📢 H264 码流是放在 RTP 的有效载荷部分的。因此有效载荷前面的 RTP 头部跟码流本身是没有关系的,所以我…...

realloc的补充 柔性数组

&#x1f436;博主主页&#xff1a;ᰔᩚ. 一怀明月ꦿ ❤️‍&#x1f525;专栏系列&#xff1a;线性代数&#xff0c;C初学者入门训练&#xff0c;题解C&#xff0c;C的使用文章&#xff0c;「初学」C &#x1f525;座右铭&#xff1a;“不要等到什么都没有了&#xff0c;才下…...

【C语言】柔性数组

柔性数组1. 柔性数组介绍2. 柔性数组特点3. 用例3.1 代码一&#xff1a;3.2 代码二&#xff1a;4. 柔性数组优势&#xff1a;1. 柔性数组介绍 也许你从来没有听说过柔性数组&#xff08;flexible array&#xff09;这个概念&#xff0c;但是它确实是存在的。 C99 中&#xff0c…...

【Linux】权限详解

前言首先我们先来看一下权限的概念&#xff1a;在多用户计算机系统的管理中&#xff0c;权限&#xff08;privilege&#xff09;是指某个特定的用户具有特定的系统资源使用权力&#xff0c;像是文件夹&#xff0c;特定系统指令的使用或存储量的限制。通常&#xff0c;系统管理员…...

Android 之 打开相机 打开相册

Android 之 打开系统摄像头拍照 打开系统相册&#xff0c;并展示1&#xff0c;清单文件 AndroidManifest.xml<uses-permission android:name"android.permission.INTERNET" /><!--文件读取权限--><uses-permission android:name"android.permiss…...

Vim 调用外部命令学习笔记

Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...

[2025CVPR]DeepVideo-R1:基于难度感知回归GRPO的视频强化微调框架详解

突破视频大语言模型推理瓶颈,在多个视频基准上实现SOTA性能 一、核心问题与创新亮点 1.1 GRPO在视频任务中的两大挑战 ​安全措施依赖问题​ GRPO使用min和clip函数限制策略更新幅度,导致: 梯度抑制:当新旧策略差异过大时梯度消失收敛困难:策略无法充分优化# 传统GRPO的梯…...

内存分配函数malloc kmalloc vmalloc

内存分配函数malloc kmalloc vmalloc malloc实现步骤: 1)请求大小调整:首先,malloc 需要调整用户请求的大小,以适应内部数据结构(例如,可能需要存储额外的元数据)。通常,这包括对齐调整,确保分配的内存地址满足特定硬件要求(如对齐到8字节或16字节边界)。 2)空闲…...

Cursor实现用excel数据填充word模版的方法

cursor主页&#xff1a;https://www.cursor.com/ 任务目标&#xff1a;把excel格式的数据里的单元格&#xff0c;按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例&#xff0c;…...

Leetcode 3576. Transform Array to All Equal Elements

Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接&#xff1a;3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到&#xf…...

【WiFi帧结构】

文章目录 帧结构MAC头部管理帧 帧结构 Wi-Fi的帧分为三部分组成&#xff1a;MAC头部frame bodyFCS&#xff0c;其中MAC是固定格式的&#xff0c;frame body是可变长度。 MAC头部有frame control&#xff0c;duration&#xff0c;address1&#xff0c;address2&#xff0c;addre…...

Docker 运行 Kafka 带 SASL 认证教程

Docker 运行 Kafka 带 SASL 认证教程 Docker 运行 Kafka 带 SASL 认证教程一、说明二、环境准备三、编写 Docker Compose 和 jaas文件docker-compose.yml代码说明&#xff1a;server_jaas.conf 四、启动服务五、验证服务六、连接kafka服务七、总结 Docker 运行 Kafka 带 SASL 认…...

ios苹果系统,js 滑动屏幕、锚定无效

现象&#xff1a;window.addEventListener监听touch无效&#xff0c;划不动屏幕&#xff0c;但是代码逻辑都有执行到。 scrollIntoView也无效。 原因&#xff1a;这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作&#xff0c;从而会影响…...

.Net Framework 4/C# 关键字(非常用,持续更新...)

一、is 关键字 is 关键字用于检查对象是否于给定类型兼容,如果兼容将返回 true,如果不兼容则返回 false,在进行类型转换前,可以先使用 is 关键字判断对象是否与指定类型兼容,如果兼容才进行转换,这样的转换是安全的。 例如有:首先创建一个字符串对象,然后将字符串对象隐…...

优选算法第十二讲:队列 + 宽搜 优先级队列

优选算法第十二讲&#xff1a;队列 宽搜 && 优先级队列 1.N叉树的层序遍历2.二叉树的锯齿型层序遍历3.二叉树最大宽度4.在每个树行中找最大值5.优先级队列 -- 最后一块石头的重量6.数据流中的第K大元素7.前K个高频单词8.数据流的中位数 1.N叉树的层序遍历 2.二叉树的锯…...