【数据结构初阶】单链表SLlist

描述

不同于顺序表,顺序表的数据是存储在一个连续的空间里的

链表它是链接起来的结构体地址。

所以我们不用像顺序表一样先创建一块空间出来,而是创建一个能存数据节点和节点与下一个节点之间的连接

所以:“一个能存数据节点”我们用int Data表示;

与下一个节点之间的连接”:我们用指针连接起来。

组织

打印

为了方便测试,我们先写个打印单链表的函数;

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

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

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

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

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

1.尾插

每在插入一个数据之前,首先得为这个结构体开辟一个结点

用malloc开辟,由于插入数据时我们都要进行开辟一个结点的操作,所以我们可以打包成一个函数


进行尾插首先就是要找到尾节点

找尾分两种情况:

1. 当*pphead本身为空时,就直接将newnode插入就可以了;

2. *pphead本身不为空时,只要找到tail->next为空的,那个就是结构体的尾了


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

尾插的本质是:原为节点中存储新的尾节点的地址

SLTNode* SLTNewnode(SLTDataType x)
{SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));if (newnode == NULL){perror("melloc fail");return NULL;}newnode->Data = x;newnode->next = NULL;return newnode;}void SLTPushBack(SLTNode** pphead, SLTDataType x)
{//创建节点SLTNode* newnode = SLTNewnode(x);if (newnode == NULL){return;}//情况一:pphead为空if (*pphead == NULL){*pphead = newnode;}//情况二:pphead不为空else{//找到尾节点SLTNode* tail = *pphead;while (tail->next){tail = tail->next;}tail->next = newnode;}
}

2.尾删

1.尾删需要断言吗?
需要,因为如果链表为空,是删不了的;


2.尾删的思路
尾删分三种讨论:

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

void SLTPopBack(SLTNode** pphead)
{assert(*pphead);//只有一个节点if ((*pphead)->next == NULL){free(*pphead);*pphead = NULL;}else{//找尾置空SLTNode* tail = *pphead;while (tail->next->next){tail = tail->next;}free(tail->next);tail->next = NULL;}}

3.头插

1.头插需要断言吗?
但是当链表为空的时候,可以插入数据,*pphead是不需要断言的。


2.头插的思路
首先先要创建一个结点,将结点的next与链表的第一个指针链接起来。最后要注意把链表的头给改成newnode。

void SLTPushFront(SLTNode** pphead, SLTDataType x)
{SLTNode* newnode = SLTNewnode(x);if (newnode == NULL){return;}newnode->next = *pphead;*pphead = newnode;
}


4.头删

1.头删需要断言吗?
空链表不能删除,所以*pphead也需要断言。

头删的思路:

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


5.查找

1.查找需要断言吗?
不需要,链表为空就返回NULL;


2.查找的思路
当链表的cur不为空,就继续逐一比对,找到了就返回cur,没找到就指向下一个,直到cur指向空;

如果还没找到,就返回NULL;

这里的phead用一级指针就可以了,因为不用修改里面的任何值;

SLTNode* SListFind(SLTNode* phead, SLTDataType x)
{SLTNode* cur = phead;while (cur){if (cur->Data == x){return cur;}cur = cur->next;}//如果没找到就返回NULLreturn NULL;
}



6.指定位置后插入

1.需要断言吗?
指定的位置pos不能为空,所以需要断言;


2.思路
创建一个新结点newnode,然后先让newnode->next = pos->next;让newnode的后面链接起来,在让pos和newnode链接起来pos->next = newnode;;

反过来写的话,由于pos->next已经被改了,所以不能是pos与newnode链接,插入就会失败;


void SLTInsertAfter( SLTNode* pos, SLTDataType x)
{assert(pos);SLTNode* newnode = SLTNewnode(x);if (newnode == NULL){return;}newnode->next = pos->next;pos->next = newnode;}



7.指定位置后删除

1.需要断言吗?
指定的位置pos不能为空,所以需要断言;

void SListEraseAfter( SLTNode* pos)
{assert(pos);if (pos->next == NULL){printf("已是最后一个,不能删\n");return;}SLTNode* cur = pos->next;pos->next = pos->next->next;free(cur);cur= NULL;
}

8.链表的销毁

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

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

关于其他的一些细节问题

为什么不像顺序表一样写初始化函数?

可写可不写,这里结构体里面的数据比较少,我们在测试代码的时候直接用指针指向了一块空间。

为什么要传二级指针?

想要改变变量的数值而不会因为栈帧的销毁而销毁,就得取到该变量的地址;

什么时候要传二级指针,什么时候要传一级指针?

想要改变变量里的数值就要传址调用,二级指针用来接收一级指针;

如果只是简单的访问就用传值调用

整个程序

.h文件

#define _CRT_SECURE_NO_WARNINGS 1#include<stdio.h>
#include<stdlib.h>
#include<assert.h>typedef int SLTDataType;typedef struct SLTlist
{SLTDataType Data;	struct SLTlist * next;}SLTNode;void SLTPrint(SLTNode* phead);
void SLTPushBack(SLTNode** pphead, SLTDataType x);
void SLTPopBack(SLTNode** pphead);
void SLTPushFront(SLTNode** pphead, SLTDataType x);
void SLTPopFront(SLTNode** pphead);
SLTNode* SListFind(SLTNode* phead, SLTDataType x);
void SLTInsertAfter( SLTNode* pos, SLTDataType x);
void SListEraseAfter( SLTNode* pos);
void SLTDel(SLTNode** pphead);

.c文件

#include"SLlist.h"void SLTPrint(SLTNode* phead)
{SLTNode* cur = phead;while (cur){printf("%d->", cur->Data);cur = cur->next;}printf("NULL\n");
}SLTNode* SLTNewnode(SLTDataType x)
{SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));if (newnode == NULL){perror("melloc fail");return NULL;}newnode->Data = x;newnode->next = NULL;return newnode;}void SLTPushBack(SLTNode** pphead, SLTDataType x)
{//创建节点SLTNode* newnode = SLTNewnode(x);if (newnode == NULL){return;}//情况一:pphead为空if (*pphead == NULL){*pphead = newnode;}//情况二:pphead不为空else{//找到尾节点SLTNode* tail = *pphead;while (tail->next){tail = tail->next;}tail->next = newnode;}
}void SLTPopBack(SLTNode** pphead)
{assert(*pphead);//只有一个节点if ((*pphead)->next == NULL){free(*pphead);*pphead = NULL;}else{//找尾置空SLTNode* tail = *pphead;while (tail->next->next){tail = tail->next;}free(tail->next);tail->next = NULL;}}void SLTPushFront(SLTNode** pphead, SLTDataType x)
{SLTNode* newnode = SLTNewnode(x);if (newnode == NULL){return;}newnode->next = *pphead;*pphead = newnode;
}void SLTPopFront(SLTNode** pphead)
{assert(*pphead);SLTNode* head = *pphead;*pphead = head->next;free(head);head = NULL;}SLTNode* SListFind(SLTNode* phead, SLTDataType x)
{SLTNode* cur = phead;while (cur){if (cur->Data == x){return cur;}cur = cur->next;}//如果没找到就返回NULLreturn NULL;
}void SLTInsertAfter( SLTNode* pos, SLTDataType x)
{assert(pos);SLTNode* newnode = SLTNewnode(x);if (newnode == NULL){return;}newnode->next = pos->next;pos->next = newnode;}void SListEraseAfter( SLTNode* pos)
{assert(pos);if (pos->next == NULL){printf("已是最后一个,不能删\n");return;}SLTNode* cur = pos->next;pos->next = pos->next->next;free(cur);cur= NULL;
}void SLTDel(SLTNode** pphead)
{assert(*pphead);SLTNode* cur = *pphead;SLTNode* prev = cur;while (cur){prev = cur->next;free(cur);cur = prev;}*pphead = cur;
}

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

鸿蒙:从0到“Hello Harmony”

效果展示 一.概述 明年华为鸿蒙就不再兼容Android生态了&#xff0c;作为拥有7亿终端用户的华为&#xff0c;建立自己的生态也是理所当然。 所以对HarmonyOS的研究也是众多开发者绕不开的坎了。 今天这篇博文主要实现一个“Hello Harmony&#xff01;”的Demo。 二.官方链接…

场景交互与场景漫游-osgGA库(5)

osgGA库 osgGA库是OSG的一个附加的工具库&#xff0c;它为用户提供各种事件处理及操作处理。通过osgGA库读者可以像控制Windows窗口一样来处理各种事件 osgGA的事件处理器主要由两大部分组成&#xff0c;即事件适配器和动作适配器。osgGA:GUIEventHandler类主要提供了窗口系统的…

基于单片机体温脉搏检测控制系统及源程序

一、系统方案 1、本设计采用51单片机作为主控器。 2、DS18B20传感器检测体温。 3、红外对接管采集心率值送到液晶1602显示。 二、硬件设计 原理图如下&#xff1a; 三、单片机软件设计 1、首先是系统初始化 /lcd1602初始化设置*/ void init_1602() { write_com(0x38); //显示…

二元分类模型评估方法

文章目录 前言一、混淆矩阵二、准确率三、精确率&召回率四、F1分数五、ROC 曲线六、AUC&#xff08;曲线下面积&#xff09;七、P-R曲线类别不平衡问题中如何选择PR与ROC 八、 Python 实现代码混淆矩阵、命中率、覆盖率、F1值ROC曲线、AUC面积 指标 公式 意义 真正例 (TP)被…

【项目设计】网络版五子棋游戏

文章目录 一、项目介绍1. 项目简介2. 开发环境3. 核心技术4. 开发阶段 二、环境搭建1. 安装 wget 工具2. 更换 yum 源3. 安装 lrzsz 传输工具4. 安装⾼版本 gcc/g 编译器5. 安装 gdb 调试器6. 安装分布式版本控制工具 git7. 安装 cmake8. 安装 boost 库9. 安装 Jsoncpp 库10. 安…

四旋翼无人机的飞行原理--【其利天下分享】

近年来&#xff0c;无人机在多领域的便捷应用促使其迅猛的发展&#xff0c;如近年来的多场战争&#xff0c;无人机的战场运用发挥得淋漓尽致。 下面我们针对生活中常见的四旋翼无人机的飞行原理做个基础的介绍&#xff0c;以飨各位对无人机有兴趣的朋友。 一&#xff1a;四旋翼…

春秋云境靶场CVE-2022-28512漏洞复现(sql手工注入)

文章目录 前言一、CVE-2022-28512靶场简述二、找注入点三、CVE-2022-28512漏洞复现1、判断注入点2、爆显位个数3、爆显位位置4 、爆数据库名5、爆数据库表名6、爆数据库列名7、爆数据库数据 总结 前言 此文章只用于学习和反思巩固sql注入知识&#xff0c;禁止用于做非法攻击。…

腐蚀监测常用技术及作用

上次我们介绍了设备状态监测中的红外热像技术>>热成像仪的工作原理及在工业设备状态监测中的应用&#xff0c;这次我们一起来探讨腐蚀监测技术方面的内容。 在工业领域中&#xff0c;腐蚀监测技术是腐蚀控制的重要部分和可靠而有效的手段。通过对设备的腐蚀情况进行监测和…

【JVM】Java虚拟机

本文主要介绍了JVM的内存区域划分,类加载机制以及垃圾回收机制. 其实JVM的初心,就是让java程序员不需要去了解JVM的细节,它把很多工作内部封装好了.但是学习JVM的内部原理有利于我们深入理解学习Java. 1.JVM的内存区域划分 JVM其实是一个java进程 ; 每个java进程,就是一个jvm…

Apache Airflow (九) :Airflow Operators及案例之BashOperator及调度Shell命令及脚本

&#x1f3e1; 个人主页&#xff1a;IT贫道_大数据OLAP体系技术栈,Apache Doris,Clickhouse 技术-CSDN博客 &#x1f6a9; 私聊博主&#xff1a;加入大数据技术讨论群聊&#xff0c;获取更多大数据资料。 &#x1f514; 博主个人B栈地址&#xff1a;豹哥教你大数据的个人空间-豹…

科技创新 共铸典范 | 江西卫健办邓敏、飞图影像董事长洪诗诗一行到访拓世科技集团,提振公共卫生事业发展

2023年11月15日&#xff0c;拓世科技集团总部迎来了江西省卫健项目办项目负责人邓敏、江西飞图影像科技有限公司董事长洪诗诗一行的考察参观&#xff0c;集团董事长李火亮、集团高级副总裁方高强进行热情接待。此次多方交流&#xff0c;旨在共同探讨携手合作&#xff0c;激发科…

Django+Vue项目创建 跑通

参考链接&#xff1a; 【精选】DjangoVue项目构建_django vue-CSDN博客 一、背景 主要介绍如何使用后端Django 前端Vue 的技术栈快速地搭建起一套web项目的框架。 为什么使用Django和Vue? Django是Python体系下最成熟的web框架之一&#xff0c;由于Python语言的易用…

【机器学习Python实战】线性回归

&#x1f680;个人主页&#xff1a;为梦而生~ 关注我一起学习吧&#xff01; &#x1f4a1;专栏&#xff1a;机器学习python实战 欢迎订阅&#xff01;后面的内容会越来越有意思~ ⭐内容说明&#xff1a;本专栏主要针对机器学习专栏的基础内容进行python的实现&#xff0c;部分…

Redux-状态管理组件

一、简介 react中的状态只属于某个组件。而Redux是一个全局管理js状态的架构&#xff0c;让组件通信更加容易。 之前是状态在所有组件间传递&#xff0c;而redux通过store来实现这个功能。 Redux特性&#xff1a; 1.Single source Of truth&#xff0c;通过store唯一维护状态…

网工内推 | 国企、港企网工,年底双薪,NA以上认证即可

01 中航期货有限公司 招聘岗位&#xff1a;信息技术部-网络工程师 职责描述&#xff1a; 1、负责总部、分支机构、外联单位网络的日常运维、故障和应急处置&#xff0c;特别是定期监测设备的运行状态&#xff0c;对存在隐患的地方及时发现改正&#xff0c;保持网络稳定通畅&am…

Java 12 及Tomcat 部署配置

使用的软件版本 1. Java12部署 和之前的Java版本不太一样&#xff0c;12版本不用配置JRE环境。 解压缩文件夹 root账户执行 tar -xzvf /home/software/jdk-12.0.2_linux-x64_bin.tar.gz创建java文件夹 root账户执行 cd /usr mkdir java移动Java文件到创建的文件夹下 root账…

多态语法详解

多态语法详解 一&#xff1a;概念1&#xff1a;多态实现条件 二:重写&#xff1a;三&#xff1a;向上转型和向下转型1:向上转型&#xff1a;1&#xff1a;直接赋值&#xff1a;2&#xff1a;方法传参3&#xff1a;返回值 2:向下转型 一&#xff1a;概念 1&#xff1a;同一个引…

LINMP搭建wordpress-数据库不分离

目录 一、nginx部署 1.安装nginx前的系统依赖环境检查 2.下载nginx源代码包 3.解压缩源码包 4.创建普通的nginx用户 5.开始编译安装nginx服务 6.创建一个软连接以供集中管理 7.配置nginx环境变量 二、mysql 1.创建普通mysql用户 2.下载mysql二进制代码包 3.创建mys…