单链表的实现(数据结构)

news2024/11/17 3:57:40

本篇博客主要是单链表(无头单项不循环)的实现的代码分享

说明:因为此单链表无头(哨兵位),可以说成没有初始化也可以说初始化时没有一个有效地址作为单链表的起始地址 例如下面代码中的plist == NULL。

  所以在后面函数(链表为空时,头插、尾插、插入)实现过程中需要将plist(单链表头结点地址)修改,就需要传址操作(在这里需要传单链表节点地址的地址),而且为了代码接口的一致性,在单链表函数实现中全部传了单链表节点地址的地址!

图解:

	SLNode* plist = NULL;//只是定义了一个单向链表节点的地址,而且地址还==NULL


	SLNodePushBack(&plist,1);

头文件Single List.h

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

typedef int SLNodeDataType;
typedef struct Single_Linked_ListNode
{
	SLNodeDataType data;
	struct Single_Linked_ListNode* next;
}SLNode;

//
void SLNodePushBack(SLNode** pphead, SLNodeDataType x);
void SLNodePushFront(SLNode** pphead, SLNodeDataType x);

void SLNodePopBack(SLNode** pphead);
void SLNodePopFront(SLNode** pphead);

SLNode* SLNodeBuyNode(SLNodeDataType x);
void SLNodePrint(SLNode** pphead);

SLNode* SLNodeFind(SLNode** pphead,SLNodeDataType x);

void SLNodeInsert(SLNode** pphead, SLNode* pos, SLNodeDataType x);
void SLNodeErase(SLNode** pphead, SLNode* pos);

void SLNodeInsertAfter(SLNode** pphead, SLNode* pos, SLNodeDataType x);
void SLNodeEraseAfter(SLNode** pphead, SLNode* pos);
     
void SListDestroy(SLNode** pphead)

源文件Single Link.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"Single List.h"


SLNode* SLNodeBuyNode(SLNodeDataType x)
{
	SLNode* tmp = malloc(sizeof(SLNode));
	if (tmp == NULL)
	{
		perror("malloc fail!");
		exit(1);
	}
	tmp->data = x;
	tmp->next = NULL;
	return tmp;
};
void SLNodePushBack(SLNode** pphead, SLNodeDataType x)
{
	assert(pphead);
	SLNode* pnewnode = SLNodeBuyNode(x);
	//链表为空,新节点做头节点
	if (*pphead == NULL)
	{
		*pphead = pnewnode;
		return;
	}

	//链表不为空,找尾节点
	SLNode* ptail= *pphead;
	while (ptail->next != NULL)
	{
		ptail = ptail->next;
	}
	ptail->next = pnewnode;

	
};
void SLNodePushFront(SLNode** pphead, SLNodeDataType x)
{
	assert(pphead);
	SLNode* pnewnode = SLNodeBuyNode(x);
	//链表为空,新节点做头节点
	if (*pphead == NULL)
	{
		*pphead = pnewnode;
		return;
	}
	//链表不为空
	pnewnode->next = *pphead;
	*pphead = pnewnode;

}

void SLNodePopBack(SLNode** pphead)
{
	assert(pphead);
	assert(*pphead);//确保有节点
	//只有一个节点
	if ((*pphead)->next == NULL)
	{
		free(*pphead);//置空前不要忘了释放空间
		*pphead = NULL;
		return;//不需要再走了
	}
	//多节点,找尾节点前一个节点
	SLNode* ptailprev = *pphead;
	while ((ptailprev->next->next) != NULL)
	{
		ptailprev = ptailprev->next;
	}
	free(ptailprev->next);
	ptailprev->next = NULL;

}
void SLNodePopFront(SLNode** pphead)
{
	assert(pphead);
	assert(*pphead);//必须有节点
	一个节点
	//if ((*pphead)->next == NULL)
	//{
	//	free(*pphead);
	//	*pphead = NULL;
	//	return;
	//}
	多个节点
	SLNode* tmp = (*pphead)->next;
	free(*pphead);
	*pphead = tmp;

}


void SLNodePrint(SLNode** pphead)
{
	SLNode* pcur = *pphead;
	while (pcur)
	{
		printf("%d->",pcur->data);
		pcur = pcur->next;
	}
	printf("NULL\n");
}

SLNode* SLNodeFind(SLNode** pphead,SLNodeDataType x)
{
	assert(pphead);
	//遍历链表
	SLNode* pcur = *pphead;
	while (pcur)
	{
		if (pcur->data == x)
		{
			return pcur;
		}
		pcur=pcur->next;
	}
	//没找到
	return NULL;
}
void SLNodeInsert(SLNode** pphead, SLNode* pos, SLNodeDataType x)
{
	assert(pphead);
	assert(pos);
	//链表不为空
	assert(*pphead);
	SLNode* pnewnode = SLNodeBuyNode(x);
	//头节点插入
	if (pos == *pphead)
	{
		SLNodePushFront(pphead,x);
		return;
	}
	//其他节点

	SLNode* prev = *pphead;
	while (prev->next!=pos)
	{
		prev = prev->next;
	}
	prev->next = pnewnode;
	pnewnode->next = pos;
}
void SLNodeErase(SLNode** pphead, SLNode* pos)
{
	assert(pphead);
	assert(pos);
	assert(*pphead);

	if (*pphead == pos)
	{  
		SLNodePopFront(pphead);
		return;
	}
	SLNode* prev= *pphead;
	while (prev->next != pos)
	{
		prev = prev->next;
	}
	SLNode* pnext = pos->next;
	pos->next = NULL;
	free(pos);
	pos = NULL;
	prev -> next = pnext;
}

void SLNodeInsertAfter(SLNode** pphead, SLNode* pos, SLNodeDataType x)
{
	
	assert(pphead);
	assert(pos);
	SLNode* pnewnode = SLNodeBuyNode(x);
	SLNode* pnext = pos->next;
	pos->next = pnewnode;
	pnewnode->next = pnext;


}
void SLNodeEraseAfter(SLNode** pphead, SLNode* pos)
{

	assert(pphead);
	assert(pos);
	assert(pos->next);
	//pos pnext pnextnext
	SLNode* pnext = pos->next;
	SLNode* pnextnext = pnext->next;
	pos->next = pnextnext;
	pnext->next = NULL;
	free(pnext);
	pnext = NULL;

}

void SListDestroy(SLNode** pphead)
{
	assert(pphead);
	assert(*pphead);

	SLNode* pcur = *pphead;
	while (pcur)
	{
		SLNode* next = pcur->next;
		free(pcur);
		pcur = next;
	}
	*pphead = NULL;
}

测试test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"Single List.h"



int main()
{
	SLNode* plist = NULL;
	SLNodePushBack(&plist,1);
	SLNodePushBack(&plist,2);
	SLNodePushBack(&plist,3);
	SLNodePushBack(&plist,4);
	SLNodePushBack(&plist,5);

	SLNodePrint(&plist);
	SLNodePushFront(&plist, 100);
	SLNodePushFront(&plist, 200);
	SLNodePushFront(&plist, 300);
	SLNodePushFront(&plist, 400);
	SLNodePrint(&plist);
	SLNodePopBack(&plist);
	SLNodePopBack(&plist);



	SLNodePrint(&plist);
	SLNodePopFront(&plist);
	SLNodePopFront(&plist);
	SLNodePopFront(&plist);


	SLNodePrint(&plist);
	SLNode* findinex = SLNodeFind(&plist,100 );
	if (findinex)
	{
		printf("找到了\n");
	}
	else
	{
		printf("未找到\n");
	}
	SLNodeInsert(&plist,findinex,1000);
	SLNodePrint(&plist);
	SLNodeErase(&plist,findinex);
	SLNodePrint(&plist);
	SLNode* findinex2 = SLNodeFind(&plist, 1000);
	if (findinex2)
	{
		printf("找到了\n");
	}
	else
	{
		printf("未找到\n");
	}
	//SLNodeErase(&plist, findinex2);
	SLNodePrint(&plist);
	SLNodeInsertAfter(&plist, findinex2, 666);
	SLNodePrint(&plist);
	SLNode* findinex3 = SLNodeFind(&plist,1000);
	if (findinex3)
	{
		printf("找到了\n");
	}
	else
	{
		printf("未找到\n");
	}
	SLNodeEraseAfter(&plist, findinex3);
	SLNodePrint(&plist);
	return 0;
	SListDestroy(&plist);
}

这个博客如果对你有帮助,给博主一个免费的点赞就是最大的帮助

欢迎各位点赞,收藏和关注哦

如果有疑问或有不同见解,欢迎在评论区留言哦

后续我会一直分享双一流211西北大学本科生我自己的软件学习过程(C,数据结构,C++,Linux,MySQL)的学习干货以

及重要代码的分享

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

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

相关文章

MS5188N——16bit、8 通道、500kSPS、 SAR 型 ADC

产品简述 MS5188N 是 8 通道、 16bit 、电荷再分配逐次逼近型模数 转换器&#xff0c;采用单电源供电。 MS5188N 拥有多通道、低功耗数据采集系统所需的所有 组成部分&#xff0c;包括&#xff1a;无失码的真 16 位 SAR ADC &#xff1b;用于将输入配 置为单端输入…

开源爬虫技术在金融行业市场分析中的应用与实战解析

一、项目介绍 在当今信息技术飞速发展的时代&#xff0c;数据已成为企业最宝贵的资产之一。特别是在${industry}领域&#xff0c;海量数据的获取和分析对于企业洞察市场趋势、优化产品和服务至关重要。在这样的背景下&#xff0c;爬虫技术应运而生&#xff0c;它能够高效地从互…

字符串索引错误解决方案

字符串索引错误通常是由于尝试访问字符串中不存在的索引位置而引起的。我在Python编译中&#xff0c;字符串是一个不可变的序列&#xff0c;可以通过索引访问其中的字符。如果尝试访问超出字符串长度范围的索引位置&#xff0c;将引发IndexError异常。所以下面的问题如果遇到了…

运维知识点-Tomcat

Tomcat tomcat日志告警tomcat文件包含读取漏洞Tomcat ### 远程代码执行(7.0.0-7.0.81) 开启PUT,访问127.0.0.1:8080改PUT,创建x.jsp,写入shellwar后文件部署,登入特定后台,上传包含jsp写的war文件。文件解析tomcat日志告警 cat catalina.sh /usr/local/tomcat/confTo…

运维知识点-JBoss

JBoss 介绍介绍 JBoss是一个基于J2EE的开放源代码的应用服务器,也是一个运行EJB(Enterprise JavaBean)的容器和服务器。它支持EJB 1.1、EJB 2.0和EJB3的规范,体现了J2EE规范中最新的技术。JBoss遵循LGPL许可,可以在任何商业应用中免费使用,并且由开源社区开发,这使得JB…

345.反转字符串中的元音字母

题目&#xff1a;给你一个字符串 s &#xff0c;仅反转字符串中的所有元音字母&#xff0c;并返回结果字符串。 元音字母包括 a、e、i、o、u&#xff0c;且可能以大小写两种形式出现不止一次。 class Solution {//画图&#xff0c;好理解点public String reverseVowels(String…

MySQL常见的存储引擎介绍

我将为您详细讲解 MySQL 常见的存储引擎&#xff0c;以及它们的使用场景、特点、区别和优势。MySQL 支持多种存储引擎&#xff0c;每种存储引擎都有其特定的优势和局限性。了解这些存储引擎的特点和适用场景对于选择合适的存储引擎以及优化数据库性能至关重要。 1. InnoDB 存储…

搞不完的事情,大不了加班?

工作是生活的一部分&#xff0c;但当你发现搞不完的事情&#xff0c;大不了加班&#xff01;你就会陷入无限的循环。 如果你想早点下班 &#xff0c;并且好好做自己的账号&#xff0c;还是少看哪些月入5万-10万的博主&#xff01; 如果你照着大V账号模仿大概率会失败&#xff…

python统计日志中数据从开始到结束的响应时间的最大值、最小值、平均值、中位数

应用场景&#xff1a;需要根据日志文件&#xff0c;统计出数据从开始下发到收到回复所需的时间&#xff0c;包括最大值、最小值、平均值、中位数。 日志格式如图类似&#xff0c;每一行日志开始部分就是所需要截取的时间&#xff1b;1条日记是以某些关键词作为开始&#xff0c;…

R语言自定义颜色

一、创建颜色梯度&#xff08;渐变色&#xff09; 在绘热图时&#xff0c;需要将数值映射到不同的颜色上&#xff0c;这时就需要一系列的颜色梯度colorRampPalette 函数支持自定义的创建一系列的颜色梯度。 代码示例&#xff1a; library(RColorBrewer)x <- colorRampPal…

从新能源汽车行业自动驾驶技术去看AI的发展未来趋势

自动驾驶汽车关键技术主要包括环境感知、精准定位、决策与规划、控制与执行、高精地图与车联网V2X以及自动驾驶汽车测试与验证技术等。 &#x1f413; 自动驾驶技术 这是AI在汽车行业中应用最广泛的领域之一。自动驾驶技术利用AI算法和传感器来感知环境、识别障碍物&#xff0c…

购买阿里云服务器如何选择实例?根据业务场景与细分场景推荐实例规格

对于很多初次购买阿里云服务器的用户来说&#xff0c;面对众多可选择的云服务器实例规格&#xff0c;往往不知道如何选择&#xff0c;不同实例规格适用于不同的业务场景&#xff0c;本文为大家汇总了不同业务场景和细分场景下应该选择的主要实例规格&#xff0c;以及这些实例规…

传统应急照明解决方案和新标准下地铁应急照明的方案区别

传统地铁站应急照明系统方案 传统地铁站应急照明系统一般设置2套或4套,给相应端区域的应急照明提供电源。由于地铁站应急照明系统设计比较成熟&#xff0c;几乎所有的地铁站接线方案均采用了经典的双电源切换加蓄电池逆变交流220/380V的配电方式.以南方某地铁站为例,此地铁站是…

YoloV8改进策略:Block改进|自研Block,涨点超猛|代码详解|附结构图

涨点效果 涨点效果:在我自己的数据集上,mAP50 由0.986涨到了0.993,mAP50-95由0.737涨到0.757,涨点明显! 参考模型 参考的Block,如下图: 我对Block做了修改,修改后的结构图如下: 代码详解 from timm.models.layers import DropPathfrom torch import Tensor def …

阿里云服务器使用教程_2024建站教程_10分钟网站搭建流程

使用阿里云服务器快速搭建网站教程&#xff0c;先为云服务器安装宝塔面板&#xff0c;然后在宝塔面板上新建站点&#xff0c;阿里云服务器网aliyunfuwuqi.com以搭建WordPress网站博客为例&#xff0c;来详细说下从阿里云服务器CPU内存配置选择、Web环境、域名解析到网站上线全流…

selenium 4.17正式发布,这几项更新值得关注

&#xff08;全文约1400字&#xff0c;阅读约需4分钟&#xff0c;首发于公众号&#xff1a;测试开发研习社&#xff0c;欢迎关注&#xff09; 两天前&#xff0c;selenium 正式发布了新版本 4.17&#xff0c;其中 python 版本的变化有更新更新值得关注 1. CDP 支持范围调整到 &…

117.龙芯2k1000-pmon(16)- linux下升级pmon

pmon的升级总是有些不方便&#xff0c;至少是要借助串口和串口工具 如果现场不方便连接串口&#xff0c;是不是可以使用网线升级pmon呢&#xff1f; 答案当然是可行的。 环境&#xff1a;2k1000linux3.10麒麟的文件系统 如今我已经把这个工具开发出来了。 GitHub - zhaozhi…

做抖店用平板能代替电脑操作吗?抖店运营相关注意事项,注意规避

我是王路飞。 之前给你们讲在抖音开店流程的时候&#xff0c;说过开店需要用到电脑&#xff0c;还需要执照、资金、时间等等。 那么做抖店用平板能代替电脑操作吗&#xff1f; 这个问题其实有很多新手问过我&#xff0c;有的甚至是想直接在手机上操作&#xff0c;想着能省点…

怎么对接迅雷网盘拉新项目?迅雷网盘怎么做才有效果?

自网盘拉新项目上线以来&#xff0c;网盘市场日益繁荣&#xff0c;各大厂商纷纷进军这一领域。头条网盘、悟空网盘、UC网盘、迅雷网盘等都成为了各个推广达人喜欢的推广项目。其中&#xff0c;迅雷网盘凭借其稳定的服务、强大的功能和广泛的用户基础&#xff0c;成为了市场中的…

西门子Mendix低代码资深技术顾问张戟,将出席“ISIG-低代码/零代码技术与应用发展峰会”

3月16日&#xff0c;第四届「ISIG中国产业智能大会」将在上海中庚聚龙酒店拉开序幕。本届大会由苏州市金融科技协会指导&#xff0c;企智未来科技&#xff08;LowCode低码时代、RPA中国、AIGC开放社区&#xff09;主办。大会旨在聚合每一位产业成员的力量&#xff0c;深入探索低…