详解C语言单链表接口函数

news2024/12/22 18:56:18

准备工作

创建一个头文件(SList.h),两个源文件(SList.c和test.c)

  • SList.h:用于包含库函数的头文件,链表节点结构体声明,接口函数的声明等【另外两个源文件要包含SList.h这个头文件,才能使用其中的声明】
  • SList.h:用于实现单链表的接口函数
  • test.c:存放main函数,用于链表的测试

——-————————–————----————————————————-——-———————————
在这里插入图片描述
上图包含了以下3个操作

1.库函数的头文件的包含:

  • stdio.h:输入/输出等函数
  • stdlib.h:动态内存申请
  • assert.h:报错函数assert

2.给链表节点的数据域的数据类型重命名
为什么要重命名呢?
这是为了以后如果改变了SL结构体中数据存储的类型时,不用到处改函数参数等地方的数据类型,只要改typedef后的int 为对应要改成的数据类型就可以。

3.链表节点结构体定义

——-————————–————----————————————————-——-———————————

打印链表

代码:

在这里插入图片描述

函数参数设计:

因为打印链表不会改变头指针,所以传输一级头指针
——-————————–————----————————————————-——-———————————

函数形象图解

在这里插入图片描述
【方框的上方框为数据域,下方框为指针域】

——-————————–————----————————————————-——-———————————

尾插

在这里插入图片描述

函数参数设计

  • SLTNodephead:
    因为当头节点为空的时候头指针指向的地址会改变
    所以传头指针的地址进去,用
    二级指针接收**
  • x:
    要插入的数据

函数原理

先动态内存申请一个节点的空间
如果链表为空,就让新的节点成为头节点,让phead指向新节点。
否则就用cur遍历链表,用prev指向cur的前一个节点【实现方式:cur指向下一个节点之前,让prev=cur】,这样当cur遍历指向NULL结束循环时,prev就指向最后一个节点,此时再尾插,让prev的指针域指向新节点,再让新节点的指针域指向NULL。

也可以省去prev,把while循环结束的条件换成cur->next,当cur->next为空时循环结束,此时cur正好指向链表的最后一个节点

图解

在这里插入图片描述
【方框的上方框为数据域,下方框为指针域】

——-————————–————----————————————————-——-———————————

头插

在这里插入图片描述

函数参数设计

  • SLTNodephead:
    因为头指针指向的地址会改变
    所以传头指针的地址进去,用
    二级指针接收**
  • x:
    要插入的数据

图解

在这里插入图片描述
【方框的上方框为数据域,下方框为指针域】

——-————————–————----————————————————-——-———————————

尾删

在这里插入图片描述

函数参数设计

  • SLTNodephead:
    因为当链表只有一个节点的时候头指针指向的地址会改变
    所以传头指针的地址进去,用
    二级指针接收**

图解

在这里插入图片描述
【方框的上方框为数据域,下方框为指针域】

——-————————–————----————————————————-——-———————————

头删

在这里插入图片描述

函数参数设计

  • SLTNodephead:
    因为头指针指向的地址会改变
    所以传头指针的地址进去,用
    二级指针接收**

图解

在这里插入图片描述
【方框的上方框为数据域,下方框为指针域】

——-————————–————----————————————————-——-———————————

随机查找

在这里插入图片描述

函数参数设计

  • SLTNode*phead
    因为打印链表不会改变头指针,所以传输一级头指针
  • x:
    查找的值

——-————————–————----————————————————-——-———————————

随机插入

在这里插入图片描述

函数参数设计

  • SLTNodephead:
    因为pos等于头指针的时候头指针指向的地址会改变
    所以传头指针的地址进去,用
    二级指针接收**
  • SLTNode*pos:
    配合随机查找函数的返回值,pos一般等于随机查找函数返回的指针
  • x
    要插入的数据

图解

在这里插入图片描述

——-————————–————----————————————————-——-———————————

随机删除

在这里插入图片描述

函数参数设计

  • SLTNodephead:
    因为pos等于头指针的时候头指针指向的地址会改变
    所以传头指针的地址进去,用
    二级指针接收**
  • SLTNode*pos:
    配合随机查找函数的返回值,pos一般等于随机查找函数返回的指针

图解

在这里插入图片描述
——-————————–————----————————————————-——-———————————

全部代码

SList.h

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>

typedef int SLTDateType;

typedef struct SListNode
{
	SLTDateType val;
	struct SListNode* next;
}SLTNode;

//打印链表
void SListPrint(SLTNode*phead);
//尾插
void SListPushBack(SLTNode** phead, SLTDateType x);
//头插
void SListPushFront(SLTNode** phead, SLTDateType x);
//尾删
void SListPopBack(SLTNode** phead);
//头删
void SListPopFront(SLTNode** phead);
//查找x,找到了返回指向x的结构指针,找不到返回NULL
SLTNode* SListFind(SLTNode* phead, SLTDateType x);
//在pos之前插入数据
void SListInsert(SLTNode** phead, SLTNode*pos, SLTDateType x);
//删除pos指向的节点
void SListEase(SLTNode** phead, SLTNode* pos);

```c

```c
在这里插入代码片

SLst.c

#include"SList.h"

void SListPrint(SLTNode* phead)
{
	SLTNode* cur = phead;//不要用直接用头节点去遍历链表,
	                     //防止之后要使用头节点时找不到头节点
	if (phead == NULL)//头结点为空
	{
		printf("NULL\n");
		return;
	}
	while (cur)//cur为空时链表遍历结束
	{
		printf("%d->",cur->val);
		cur = cur->next;//让cur指向下一个节点
	}
	printf("NULL");
}

void SListPushBack(SLTNode** phead, SLTDateType x)
{
	SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));//动态内存申请一个节点的空间
	if (newnode == NULL)//malloc失败时返回NULL
	{
		printf("节点malloc失败");
		exit(1);//结束程序
	}
	SLTNode* cur = *phead;

	SLTNode* prev = *phead;//prev指向cur的前一个节点
	if (*phead == NULL)
	{
		*phead = newnode;//头结点为空就让新节点成为头
		newnode->next = NULL;//此时新节点为最后一个节点,所以其指针域指向NULL
		newnode->val = x;//存放数据
	}
	else
	{
		while (cur)//遍历链表找到链表的最后一个节点
		{
			prev = cur;//让prev指向cur的前一个节点
			cur = cur->next;
		}
		newnode->val = x;
		prev->next = newnode;//此时prev为尾插前链表的最后一个节点,让它的指针域指新节点
		newnode->next = NULL;
	}
}

void SListPushFront(SLTNode** phead, SLTDateType x)
{
	SLTNode* newnode= (SLTNode*)malloc(sizeof(SLTNode));
	if (newnode == NULL)
	{
		printf("节点malloc失败");
		exit(1);
	}
	if (*phead == NULL)
	{
		*phead = newnode;//让新节点成为头结点
		newnode->next = NULL;
		newnode->val = x;//存放数据
	}
	else
	{
		SLTNode* cur = *phead;//防止找不到   原头节点
		*phead = newnode;//让新节点成为头结点
		newnode->next = cur;//让新节点连接上  原头结点
		newnode->val = x;
	}
}

void SListPopBack(SLTNode** phead)
{
	assert(*phead!=NULL);//不能一直删,当链表删空了的时候,再删就报错
	SLTNode* prev = *phead;//prev指向cur的前一个节点
	SLTNode* cur = *phead;
	while (cur->next)//当cur指向最后一个节点时,结束循环
	{
		prev = cur;//循环结束时   prev指向链表的倒数第二个节点
		cur = cur->next;
	}
	if (cur == *phead)//当链表只有头节点时
	{
		free(cur);
		*phead = NULL;//为防止野指针,让phead中存放的地址置空
		return;//结束函数
	}
	prev->next = NULL;//删除了最后一个节点时,让倒数第二个节点的指针域指向NULL
	free(cur);
}

void SListPopFront(SLTNode** phead)
{
	assert(*phead != NULL);//不能一直删,当链表删空了的时候,再删就报错

	SLTNode* cur = (*phead)->next;//让cur指向链表的第二个节点,当链表只有一个节点时cur就等于NULL

	free(*phead);//释放头节点指向的空间

	*phead = cur;//让新的头节点指向删之前的链表的第二个节点
}

//查找数据域等于x的节点,找到了返回指向x的结构指针,找不到返回NULL
SLTNode* SListFind(SLTNode* phead, SLTDateType x)
{
	if (phead == NULL)//如果链表为空,就肯定找不到
		return NULL;
	else
	{
		SLTNode* cur = phead;
		while (cur)//遍历链表
		{
			if (cur->val == x)//如果节点的数据域的值为要找的x
			{
				return cur;//找到了就返回
			}
			else
			{
				cur = cur->next;//不等于就让cur指向下一个节点
			}
		}
		return NULL;//遍历完链表还找不到就是没有数据域为x的节点
	}
}

//在pos之前插入数据
void SListInsert(SLTNode** phead, SLTNode* pos, SLTDateType x)
{
	assert(pos != NULL);//pos不能为空
	SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
	if (newnode == NULL)
	{
		printf("节点malloc失败");
		exit(1);
	}
	SLTNode* cur = *phead;
	if (pos == *phead)//当pos指向头结点时,相当于头插
	{
		cur = *phead;//防止原头节点找不到了
		*phead = newnode;
		newnode->next = cur;
		newnode->val = x;
	}
	else
	{
		SLTNode* prev = *phead;//prev指向cur的前一个节点
		while (cur)
		{
			if (cur == pos)
			{
				prev->next = newnode;//当cur==pos时,prev指向pos的前一个节点
				newnode->next = cur;//让新节点连接上pos
				newnode->val = x;
				return;//插入完成就返回
			}
			prev = cur;//cur不等于pos就让prev指向cur的当前指向的节点
			cur = cur->next;//让cur指向后一个节点
		}
	}
}

//删除pos指向的节点
void SListEase(SLTNode** phead, SLTNode* pos)
{
	assert(*phead != NULL);//不能一直删,当链表删空了的时候,再删就报错
	assert(pos != NULL);//pos不能为空
	SLTNode* tmp = pos->next;//存储pos的下一个节点,防止pos释放后找不到pos的下一个节点
	SLTNode* cur = *phead;
	if (pos == *phead)
	{
		free(*phead);
		*phead = tmp;//让phead指向pos的下一个节点
		return;
	}
	while (cur)
	{
		if (cur->next == pos)//此时cur指向pos的前一个节点
		{
			cur->next = tmp;
			free(pos);
		}
		cur = cur->next;//不等于就让cur指向下一个节点
	}
}

``

以上就是全部内容了,如果对你有帮助的话,可以点个赞支持一下!

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

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

相关文章

【项目管理】CMMI-项目总体计划模版

目录 1、总体目录结构 2、重点章节概要示例 2.1 第四章 项目管理 2.2 第六章 实施与交付计划 2.3 第七章 运维计划 1、总体目录结构 2、重点章节概要示例 2.1 第四章 项目管理 2.2 第六章 实施与交付计划 2.3 第七章运维计划

【2023年终总结】纵是一路仆仆风尘,也莫忘了仰头

文章目录 1. 写在前面2. 关于生活3. 关于工作4. 关于以后 【作者主页】&#xff1a;吴秋霖 【作者介绍】&#xff1a;Python领域优质创作者、阿里云博客专家、华为云享专家。长期致力于Python与爬虫领域研究与开发工作&#xff01; 【作者推荐】&#xff1a;对JS逆向感兴趣的朋…

vue3+ts+vite自定义组件上传npm流程

1. 创建项目 npm create vite 这里踩坑点&#xff1a; 运行vite生成的vue项目时报错“SyntaxError: Unexpected token ?? at “ 是因为node版本过低 电脑为windows11系统&#xff0c;我当时使用的版本node版本是14.21.3&#xff0c;如下图&#xff0c;后边安装了nvm版本…

Redisson依赖冲突记录

前言&#xff1a;项目使用的springboot项目为2.7.X 依赖冲突一&#xff1a;springboot 与 redisson版本冲突 项目中依赖了 Lock4j&#xff0c;此为苞米豆开源的分布式锁组件 <dependency><groupId>com.baomidou</groupId><artifactId>lock4j-redisso…

《面向复杂仿真元建模的序贯近邻探索实验设计方法》论文复现

# peaks函数热力图 from matplotlib import pyplot as plot import numpy as np import math from mpl_toolkits.mplot3d import Axes3D#python绘图显示中文 plot.rcParams[font.sans-serif][SimHei] plot.rcParams[axes.unicode_minus] False#创建画布 fig plot.figure(figs…

GPT系列概述

OPENAI做的东西 Openai老窝在爱荷华州&#xff0c;微软投资的数据中心 万物皆可GPT下咱们要失业了&#xff1f; 但是世界不仅仅是GPT GPT其实也只是冰山一角&#xff0c;2022年每4天就有一个大型模型问世 GPT历史时刻 GPT-1 带回到2018年的NLP 所有下游任务都需要微调&#x…

sudo: /usr/bin/sudo must be owned by uid 0 and have the setuid bit set问题解决方案

sudo: /usr/bin/sudo must be owned by uid 0 and have the setuid bit set问题解决方案 当我们使用sudo su切换权限时提示错误&#xff1a; sudo: /usr/bin/sudo must be owned by uid 0 and have the setuid bit set该错误出现原因&#xff1a;是因为/usr/bin/sudo的权限被…

计算机网络复习5

传输层——端到端 文章目录 传输层——端到端功能传输层的寻址与端口UDPTCPTCP连接管理TCP可靠传输TCP流量控制TCP拥塞控制网络拥塞的处理 功能 从通信和信息处理的角度看&#xff0c;传输层向它上面的应用层提供通信服务&#xff0c;它属于面向通信部分的最高层&#xff0c;同…

再升级|川石教育鸿蒙应用开发4.0教程发布

全新鸿蒙蓄势待发 HarmonyOS是一款面向未来的全场景分布式智慧操作系统。 对于消费者而言&#xff0c;HarmonyOS用一个统一的软件系统从根本上解决消费者面对大量智能终端体验割裂的问题&#xff0c;为消费者带来统一、便利、安全的智慧化全场景体验。 对于开发者而言&#xf…

现在AI那么发达,还有必要系统地学习Excel吗?

随着人工智能&#xff08;AI&#xff09;技术的飞速发展&#xff0c;许多传统的工作和技能正在逐渐被自动化和取代。在这个背景下&#xff0c;一些人开始质疑学习Excel等传统技能的必要性。然而&#xff0c;我认为学习Excel仍然是非常有必要的&#xff0c;原因如下。 首先&…

.NET DevOps 接入指南 | 1. GitLab 安装

引言 容器、DevOps和微服务被称为驱动云原生快速发展的三架马车。而DevOps是其中非常重要的一环&#xff0c;DevOps 是由Developers&#xff08;Dev&#xff09;和Operations&#xff08;Ops&#xff09;两个单词简称组成&#xff0c;中文直译就是“开发运维一体化”。 DevOps…

python大于等于小于等于,python大于等于怎么写

大家好&#xff0c;小编为大家解答python中大于等于且小于等于的问题。很多人还不知道python大于号小于号如何运用&#xff0c;现在让我们一起来看看吧&#xff01; 大家好&#xff0c;小编来为大家解答以下问题&#xff0c;python中大于并小于一个数代码&#xff0c;python 大…

STL——stack容器

1.stack基本概念 概念&#xff1a;stack是一种先进后出&#xff08;First In Last Out,FILO&#xff09;的数据结构&#xff0c;它只有一个出口。 栈中只有顶端的元素才可以被外界使用&#xff0c;因此栈不允许有遍历行为。 栈中进入数据称为——入栈&#xff08;push&#x…

大模型系列:OpenAI使用技巧_自定义文本向量化embeding

文章目录 0. Imports1. 输入2. 加载和处理输入数据3. 将数据分成训练和测试集4. 生成合成的负样本5. 计算嵌入和余弦相似度6. 绘制余弦相似度的分布图7. 使用提供的训练数据优化矩阵。8. 绘制训练期间找到的最佳矩阵的前后对比图&#xff0c;展示结果 本笔记本演示了一种将Open…

计算每个月的天数

大家好呀&#xff0c;今天的每日一题来喽。准备好了吗亲。上车上车&#xff01;&#xff01;&#xff01; 文章目录 目录 文章目录 题目重现 输⼊y和m两个整数&#xff0c;y表⽰年份&#xff0c;m表⽰⽉份&#xff0c;计算y年m⽉有多少天&#xff0c;并输出天数。 一、解法思路…

k8s之陈述式资源管理

1.kubectl命令 kubectl version 查看k8s的版本 kubectl api-resources 查看所有api的资源对象的名称 kubectl cluster-info 查看k8s的集群信息 kubectl get cs 查看master节点的状态 kubectl get pod 查看默认命名空间内的pod的信息 kubectl get ns 查看当前集群所有的命…

遍历二叉树的Morris序

参考书&#xff1a;《程序员代码面试指南》 这种方法的好处在于&#xff0c;它做到了时间复杂度为O(n)&#xff0c;额外空间复杂度为O(1)&#xff08;只申请几个变量就可以完成整个二叉树的遍历&#xff09;。 Morris遍历时cur访问节点的顺序就是morris序&#xff0c;可以在M…

大模型系列:OpenAI使用技巧_在文本向量化的交易数据做多标签分类

本笔记本涵盖了数据未标记但具有可用于将其聚类为有意义的类别的特征的用例。聚类的挑战在于使那些使得这些聚类突出的特征可读&#xff0c;这就是我们将使用GPT-3生成有意义的聚类描述的地方。然后&#xff0c;我们可以使用这些描述来为以前未标记的数据集应用标签。 为了向模…

大数据技术16:数据湖和湖仓一体

前言&#xff1a;近几年大数据概念很多&#xff0c;数据库和数据仓库还没搞清楚&#xff0c;就又出了数据湖&#xff0c;现在又开始流行湖仓一体。互联网公司拼命造高大上概念来忽略小白买单的能力还是可以的。 1、数据库 数据库是结构化信息或数据的有序集合&#xff0c;一般以…

分享一款超强大的抖音数据采集工具

你好&#xff0c;我是坚持分享干货的 EarlGrey&#xff0c;翻译出版过《Python编程无师自通》、《Python并行计算手册》等技术书籍。 如果我的分享对你有帮助&#xff0c;请关注我&#xff0c;一起向上进击。 创作不易&#xff0c;希望大家给一点鼓励&#xff0c;把公众号设置为…