【数据结构初阶】单链表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.mzph.cn/news/151194.shtml

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

相关文章

词向量笔记

一、词向量的世界排名比赛MTEB MTEB: Massive Text Embedding Benchmark 二、词向量的维数 词向量的维数d1一般取20~500之间

百分点科技|怎样做数据运营,才能让数据中台真正用起来?

导读&#xff1a;大多数企业用户已完成数据平台初步建设工作&#xff0c;但数据在业务运营和管理中没有发挥应有价值。数据开发工作繁重&#xff0c;数据质量问题严重&#xff0c;IT、数据和业务协作不畅&#xff0c;诸多问题依然困扰着企业用户的IT部门和数据部门。数据运营成…

起立科技(起鸿)在第25届高交会上展示透明OLED技术创新

第二十五届中国国际高新技术成果交易会 日期&#xff1a;2023年11月15日 地点&#xff1a;福田会展中心7号馆 深圳&#xff0c;2023年11月15日 — 起鸿科技&#xff0c;作为透明OLED领域的引领者&#xff0c;于今日参展了第二十五届中国国际高新技术成果交易会。这一展会将汇…

『亚马逊云科技产品测评』活动征文|通过lightsail一键搭建Drupal VS 手动部署

『亚马逊云科技产品测评』活动征文&#xff5c;通过lightsail一键搭建Drupal 提示&#xff1a;授权声明&#xff1a;本篇文章授权活动官方亚马逊云科技文章转发、改写权&#xff0c;包括不限于在 Developer Centre, 知乎&#xff0c;自媒体平台&#xff0c;第三方开发者媒体等亚…

微服务架构中的 熔断和降级

文章目录 熔断判定服务的健康状态服务恢复正常 降级跨服务降级自身服务提供有损服务具体案例分析 熔断 微服务架构中&#xff0c;如果需要保障可用性&#xff0c;其中一个方式就是 熔断。熔断在微服务架构里面是指 当微服务本身出现问题的时候&#xff0c;它会拒绝新的请求&am…

大学生如何免费认证,下载,安装MATLAB

下载 打开学校图书馆官网 选择版本后&#xff0c;点击下载 注册绑定个人认证 前提&#xff01;需要有学校邮箱【以edu.cn结尾的】 进入mathworks官网 注册账户 安装 下载完后&#xff0c;打开 选择&#xff1a;setup 安装程序 勾选&#xff1a;是&#xff1b;选择&#xf…

机器学习第10天:集成学习

文章目录 机器学习专栏 介绍 投票分类器 介绍 代码 核心代码 示例代码 软投票与硬投票 bagging与pasting 介绍 核心代码 随机森林 介绍 代码 结语 机器学习专栏 机器学习_Nowl的博客-CSDN博客 介绍 集成学习的思想是很直观的&#xff1a;多个人判断的结合往往比…

身份证阅读器和社保卡读卡器Harmony鸿蒙系统ArkTS语言SDK开发包

项目需求&#xff0c;用ArkTS新一代开发语言实现了在Harmony鸿蒙系统上面兼容身份证阅读器和社保卡读卡器&#xff0c;调用了DonseeDeviceLib.har这个读卡库。 需要注意的是&#xff0c;鸿蒙系统的app扩展名为.hap&#xff0c;本项目编译输出的应用为&#xff1a;entry-default…

下厨房网站月度最佳栏目菜谱数据获取及分析PLus

目录 概要 源数据获取 写Python代码爬取数据 Scala介绍与数据处理 1.Sacla介绍 2.Scala数据处理流程 数据可视化 最终大屏效果 小结 概要 本文的主题是获取下厨房网站月度最佳栏目近十年数据&#xff0c;最终进行数据清洗、处理后生成所需的数据库表&#xff0c;最终进…

JPA整合Sqlite解决Dialect报错问题, 最新版Hibernate6

前言 我个人项目中&#xff0c;不想使用太重的数据库&#xff0c;而内嵌数据库中SQLite又是最受欢迎的&#xff0c; 因此决定采用这个数据库。 可是JPA并不支持Sqlite&#xff0c;这篇文章就是记录如何解决这个问题的。 原因 JPA屏蔽了底层的各个数据库差异&#xff0c; 但是…

竞赛 题目:基于深度学习的中文对话问答机器人

文章目录 0 简介1 项目架构2 项目的主要过程2.1 数据清洗、预处理2.2 分桶2.3 训练 3 项目的整体结构4 重要的API4.1 LSTM cells部分&#xff1a;4.2 损失函数&#xff1a;4.3 搭建seq2seq框架&#xff1a;4.4 测试部分&#xff1a;4.5 评价NLP测试效果&#xff1a;4.6 梯度截断…

亚马逊第二个大语言模型 Olympus 即将上线

据外媒爆料&#xff0c;亚马逊正在训练他的第二个大语言模型——Olympus&#xff0c;很有可能在今年12月份上线。亚马逊计划将Olympus接入在线零售商店、Echo等设备上的Alexa语音助手&#xff0c;并为AWS平台提供新的功能。据说这个大语言模型规模达到2万亿&#xff08;2000B&a…

读《Segment Anything in Defect Detection》

摘要 (好像只是说把SAM应用到了红外缺陷分割领域) 引言 无损检测得到红外图像&#xff0c;根据热能观察异常 贡献&#xff1a; •从两个光学脉冲热成像系统构建广泛的缺陷热数据库&#xff0c;包括各种材料并释放它们。 • 开发DefectSAM&#xff0c;这是第一个用于缺陷检测…

MAC地址注册的网络安全影响和措施分析

MAC地址注册对网络安全具有重要影响&#xff0c;同时也需要采取相应的措施来应对潜在的安全风险。以下是有关MAC地址注册的网络安全影响和应对措施的分析&#xff1a; 影响&#xff1a; 1. 身份验证&#xff1a;MAC地址注册可用于设备的身份验证&#xff0c;但MAC地址本身并不…

不标年份的葡萄酒质量好吗?

我们在葡萄酒标上经常看到生产年份&#xff0c;也就是指全部葡萄采摘的年份。旧世界葡萄酒产国认为葡萄酒年份对他们的影响较大&#xff0c;而新世界葡萄酒&#xff0c;年份的意义就稍微小些。甚至有一部分葡萄酒酒标上没有年份。在酒标上没有标注年份的葡萄酒&#xff0c;被称…

学习无人机代码框架【第一天】---VMware 安装Ubuntu16.04时显示不全的解决方法

ros环境配置篇 环境配置在vmware上安装ubantu16.04操作系统安装完成后显示界面太小解决办法其他遇到的一些ubantu问题最后一步是在ubantu16上安装ros-kinetic其他很重要的一个工具是安装vmware-tool&#xff0c;可以支持把外部的文件或文字传入到虚拟机中管理不同的终端的软件代…

[C/C++] 数据结构 LeetCode:用队列实现栈

题目描述: 请你仅使用两个队列实现一个后入先出&#xff08;LIFO&#xff09;的栈&#xff0c;并支持普通栈的全部四种操作&#xff08;push、top、pop 和 empty&#xff09;。 实现 MyStack 类&#xff1a; void push(int x) 将元素 x 压入栈顶。int pop() 移除并返回栈顶元…

kubernetes集群编排——etcd

备份 从镜像中拷贝etcdctl二进制命令 [rootk8s1 ~]# docker run -it --rm reg.westos.org/k8s/etcd:3.5.6-0 sh 输入ctrlpq快捷键&#xff0c;把容器打入后台 获取容器id [rootk8s1 ~]# docker ps 从容器拷贝命令到本机 docker container cp c7e28b381f07:/usr/local/bin/etcdc…

最大子段和(分治法+动态规划法)

求最大子段和 此类问题通常是求数列中连续子段和的最大值&#xff0c;经典的股票问题就是考察的这个思想及拓展。 例题&#xff1a; AcWing:1054. 股票买卖 Leetcode:53. 最大子数组和 分治法O(nlogn) 此类问题时分适合采用分治思想&#xff0c;因为所有子区间 [ s t a r t …

要事第一:如何通过6个步骤确定项目的优先级

当收到很多项目请求并且每个请求都是重中之重时&#xff0c;该怎么办&#xff1f;从最易完成的开始&#xff1f;还是先解决最大的问题&#xff1f; 实际上两种做法都不对。确定项目优先级的更好方法是评估以下内容&#xff0c;而不是关注项目规模或完成时长&#xff1a; ● 每…