单链表(第二部分)单链表的实现!!!

news2024/11/24 20:39:20

1.单链表的头文件

#pragma once
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<string.h>
#include"contact.h"


typedef struct PersonInfo SLTDataType;
typedef struct SListNode
{
	//
	SLTDataType data;
	struct SListNode* next;
}SLTNode;


void SLTPrint(SLTNode* phead);

//头部插入删除/尾部插入删除
void SLTPushBack(SLTNode** pphead, SLTDataType x);
void SLTPushFront(SLTNode** pphead, SLTDataType x);
void SLTPopBack(SLTNode** pphead);
void SLTPopFront(SLTNode** pphead);

//查找
SLTNode* SLTFind(SLTNode** phead, SLTDataType x);
//在指定位置之前插入数据
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x);
//删除pos节点
void SLTErase(SLTNode** pphead, SLTNode* pos);
//在指定位置之后插入数据
void SLTInsertAfter(SLTNode* pos, SLTDataType x);
//删除pos之后的节点
void SLTEraseAfter(SLTNode* pos);
//销毁链表
void SListDesTroy(SLTNode** pphead);

为什么一些接口的参数是二级指针一些是一级指针?

因为二级指针可以对 头结点pphead 进行更改,如果只是一级指针的话形参只是一个局部变量并不能更改 pphead 的值。

就假如一个 add(int a,int b),你的两个形参都是int并没有用 int * 接收的话,那么传入的值是不会更改的。 

2.前置声明

typedef struct PersonInfo SLTDataType;
typedef struct SListNode
{
	//
	SLTDataType data;
	struct SListNode* next;
}SLTNode;

这一步主要是把每个节点要存储的数据类型确定,然后在用结构体 存储一个 数据,一个结构体指针。并且重命名为sltnode。 

2.1关于节点的开辟 

SLTNode* SLBuyNode(SLTDataType x)
{
	SLTNode* node = (SLTNode*)malloc(sizeof(SLTNode));
	node->data = x;
	node->next = NULL;
	return node;
}

返回的是一个结构体指针 ,这就是相当于是一块新的火车车厢,还没插入的。

首先传入一个值 x。用node 指针开辟一块新的空间,大小就为sltnode。

里面的值就是 x 然后下一个指针就是 置为NULL。返回node 指针就可以了。

3.打印单链表数据

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

因为打印不需要更改节点信息,所以接受的参数用一级指针即可。 用一个 中间变量pcur,进行遍历,遍历的条件就是让pcur 走到下一个数据为NULL的时候结束,因为节点的开辟时最后一个节点下一个节点必定为NULL。

最后在打印一个NULL就可以了。

4.尾部插入和头部插入

4.1尾部删除

void SLTPushBack(SLTNode** pphead, SLTDataType x)
{
	assert(pphead);
	SLTNode* node = SLBuyNode(x);
	if (*pphead == NULL)
	{
		*pphead = node;
		return;
	}
	else
	{
		SLTNode* pcur = *pphead;
		while (pcur->next != NULL)
		{
			pcur = pcur->next;
		}
		pcur->next = node;
	}
}

 1.断言pphead 是否为空指针。因为空指针不能被解引用。

2.开辟一个新的节点node。

3.判断第一个节点是不是为空,如果为空直接把node 作为第一个节点。

4.如果不是空 将第一个的节点 给 pcur 接收,用pcur 遍历到最后一个节点。跳出循环

5.将pcur 的下一个节点置为node。

4.2头部插入

void SLTPushFront(SLTNode** pphead, SLTDataType x)
{
	assert(pphead);
	SLTNode* node = SLBuyNode(x);
	node->next = *pphead;
	*pphead = node;
}

代码相对尾插断。因为不用判断第一个节点是否为空。

因为对于头插如果你的第一个节点为空也没事,因为是把节点往头结点前面插入,这样就不会解引用到空指针。

1.首先断言pphead 是否为空

2.开辟一个 名字为node 的新空间的指针。

3.将node 里的next 指针 的空间置为 *pphead (头结点)。

4.将node 变为新的头结点。 

 

5.尾部删除和头部删除

5.1尾部删除

void SLTPopBack(SLTNode** pphead)
{
	assert(pphead);
	assert(*pphead);
	SLTNode* prev = NULL;
	SLTNode* ptail = *pphead;
	while (ptail->next != NULL)
	{
		prev = ptail;
		ptail = ptail->next;
	}
	prev->next = ptail->next;
	free(ptail);
	ptail = NULL;
}

1.先用断言判断pphead 和 *pphead 是否为空(因为是删除,所以头结点不应该为空。)

2.需要用到两个指针,prev指针先指向空,ptail指针指向第一个节点。

3.用ptail去遍历链表 ,每一次将 prev 指针指向 ptail 现在在的空间。然后ptail继续往下走。

直到ptail 的下一个 空间为空。

此时ptail 在尾结点,prev在尾结点的前一个节点。

4.先让 ptail 指向下一个空间的指针指向 prev 的下一个空间,即尾空间。然后释放ptail的空间,再把ptail置为空。 

 

5.2头部删除 

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

1.删除都要断言 pphead 和* pphead 是否为空。

2.设置一个del指针指向头指针。 

3.头结点变为头结点的下一个节点。

4.将之前的头结点 del 指针的空间释放掉,并置空。

6.查找位置

SLTNode* SLTFind(SLTNode** pphead, SLTDataType x)
{
	assert(pphead);
	SLTNode* pcur = *pphead;
	while (pcur)
	{
		if (strcmp(pcur->data.name,x.name)== 0)
		{
			return pcur;
		}
		pcur = pcur->next;
	}
	return NULL;
}

 这个接口很重要,因为后续的接口都会用到。(这里采用的是查找名字的方法寻找)

1.断言pphead是否为空

2.用一个 pcur 接收 *pphead(不让头结点改变)。

3.遍历pcur 直到空

4.用strcmp比较两个名字的数据,如果相同则为0,不同则不为0.

相同返回pcur即可。

5.如果遍历结束还没找到则就返回一个空指针。

7.在指定位置之前插入数据

void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x)
{
	assert(pphead);
	assert(pos);
	assert(*pphead);
	SLTNode* node = SLBuyNode(x);
	if (pos == *pphead)
	{
		node->next = *pphead;
		*pphead = node;
		return;
	}
	SLTNode* prev = *pphead;
	while (prev->next != pos)
	{
		prev = prev->next;
	}
	prev->next = node;
	node->next = pos;
	
}

 1.断言 pphead pos *pphead(因为是指定位置所以头结点不能为空和 传入的pos位置节点也不能为空)

2.同样先创建一个node节点。

3.如果pos 找到的就是头结点,则再执行一次头插即可。

4.如果不是pos 找到的不是头结点,用prev 接收 头结点。遍历prev ->next 直到找到pos节点。找到后将prev的下一个节点的指针置为node,将node的下一个指针指向pos即可。

 

8.删除指定位置数据

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

	SLTNode* prev = *pphead;
	while (prev->next != pos)
	{
		prev = prev->next;
	}
	prev->next = pos->next;
	free(pos);
	pos = NULL;
}

 1.断言pphead和pos 和*pphead(指定位置那就代表必须要有数据)

2.如果头结点就是pos 指针。那就执行一次头删即可。

3.如果不是那一样的用两个指针,找到最后一个节点和最后一个节点前的一个节点。

将prev的next 置为 pos 的next。即可,

4.最后释放掉pos的空间。(为什么不直接删呢?因为pos里存储下一个空间的指针,如果直接删除那就找不到下一块空间的地址了。)

 

9.在指定位置之后插入数据

void SLTInsertAfter(SLTNode* pos, SLTDataType x)
{
	assert(pos);
	SLTNode* node = SLBuyNode(x);
	node->next = pos->next;
	pos->next = node;
}

 和上述类似,不会的可以私聊我,看到后给出解答

10.删除指定位置之后的节点

void SLTEraseAfter(SLTNode* pos)
{
	assert(pos);
	SLTNode* del = pos->next;
	pos->next = del->next;
	free(del);
	del = NULL;
}

 和上述类似,不会的私聊我,看到后给出解答

11.销毁链表

void SListDesTroy(SLTNode** pphead)
{
	assert(pphead);
	SLTNode* pcur = *pphead;
	while (pcur)
	{
		SLTNode* next = pcur->next;
		free(pcur);
		pcur = next;
	}
	*pphead = NULL;
}

不能直接销毁要一个一个进行销毁。因为要通过前一个空间的钥匙找到下一个空间的位置。

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

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

相关文章

技术文档工具『Writerside』抢鲜体验

前言 2023 年 10 月 16 日&#xff0c;JetBrains 宣布以早期访问状态推出 Writerside&#xff0c;基于 IntelliJ 平台的 JetBrains IDE&#xff0c;开发人员可使用它编写、构建、测试和发布技术文档&#xff0c;可以作为 JetBrains IDE 中的插件使用&#xff0c;也可以作为独立…

2023年中国汽车塑料模具市场规模、竞争格局及行业趋势分析[图]

汽车注塑模具主要用来制造汽车内外饰件以及座椅等其他塑料零部件&#xff0c;其中又以汽车内外饰件模具最多。汽车内外饰件主要由各类塑料、表皮、织物或复合材料制成&#xff0c;用到的模具主要是塑料模具。从现代汽车使用的材料来看&#xff0c;无论是外装饰件、内装饰件&…

【剑指Offer】36.二叉搜索树与双向链表

题目 输入一棵二叉搜索树&#xff0c;将该二叉搜索树转换成一个排序的双向链表。如下图所示 数据范围&#xff1a;输入二叉树的节点数 0≤n≤1000&#xff0c;二叉树中每个节点的值 0≤val≤1000 要求&#xff1a;O(1)&#xff08;即在原树上操作&#xff09;&#xff0c;时间…

爱尔眼科眼底病论坛糖网病变智能(AI)监测防治培训举办!

为推动四川省眼科学领域的学科建设、规范诊疗行为、提高学术水平&#xff0c;促进国内眼底病学学术交流。由成都高新医学会主办&#xff0c;爱尔眼科集团、爱尔眼科四川省区承办的成都高新医学会第二届眼科学术会议一一爱尔眼科眼底病论坛暨糖尿病视网膜病变智(AI)终生监测防治…

读卡器+芯片

RFID Reader 产品参数 产品型号 RFID Reader 尺寸(mm) 104*70*11.7mm 外观颜色 黑 材质 ABS 接口 MINI 功率 0.1W 电源 5V/1A 读卡距离 40mm 工作温度 -40~85℃ 工作频率 13.56Mhz 串口功能 支持 支持协议 ISO/IEC 14443、ISO/IEC 15693 产品参数 …

2023年中国石英矿资源现状及行业市场供需分析[图]

石英矿为常见的非金属矿物质&#xff0c;具有储量大、分布广、易开采等特点&#xff0c;根据不同成矿特性和理化特性&#xff0c;石英矿物可分为岩浆岩型、变质型、热液型、沉积型&#xff0c;对应的石英岩分别为花岗伟晶岩、脉石英岩、石英岩和石英砂岩。 石英矿物类型和特点…

关于在公众号刷到自己博客这件事

微信公众号 探索云原生 正式启用了&#xff0c;欢迎大家关注。 吐槽&#xff1a;竟然在微信公众号刷到自己的文章&#x1f923;&#xff0c;这也太巧了吧。 吐槽&#xff1a;这也太巧了吧 周五&#xff0c;开心的下班回到家&#xff0c;刷会微信。 发现关注的某大佬的公众号又…

laravel框架介绍(二) composer命令下载laravel报错

1.composer命令下载laravel报如下错 &#xff1a; curl error 18 while downloading https://repo.packagist.org/p2/symfony/uid.j son: transfer closed with 3808 bytes remaining to read&#xff0c;具体为 解决方案&#xff1a;执行以下命令切换镜像 >composer con…

滚动条样式美化

css手搓 <script setup> import { ref } from "vue"; </script><template><div class"ii"><div>ssssssssssssss</div><div>ssssssssssssss</div><div>ssssssssssssss</div><div>sssss…

【Python语言速回顾】——函数模块类与对象

目录 引入 一、函数 1、函数概述 2、参数和返回值 3、函数的调用 二、模块 1、模块概述 2、模块应用实例 三、类与对象 1、面向对象概述 2、类 3、类的特点 引入 为了使程序实现的代码更加简单。需要把程序分成越来越小的组成部分&#xff0c;3种方式——函数、对象…

10.26 来 CNCC 2023 T16 展位,TDengine 精美周边等你来领!

10 月 26 日你在哪&#xff1f; 这一天 TDengine 在美丽的大沈阳&#xff01; 没错 TDengine 受邀来参加中国计算机大会&#xff08;CNCC2023&#xff09;啦 在 CNCC T16 展位上 我们准备了很多精美周边礼品 等你来面基&#xff01; 另外我们还有一个好消息要分享 如果有…

Python-Pychram使用

1. pip命令安装库 一般pip安装库包&#xff0c;直接用下面命令即可&#xff1a; pip install package_name 指定安装库包的版本 pip instal package_namex.x.x 使用镜像源提高下载的速度&#xff08;这里用清华镜像源&#xff09; pip intall package_name -i https://pypi.tu…

公司如何选择数据防泄密软件

随着互联网信息的发展&#xff0c;很多企业的各类数据都是以电子文件的形式保存在员工电脑上&#xff0c;数据泄露的问题频发&#xff0c;并且在呈不断增加的趋势&#xff0c;造成的各种损失也是呈扩大的态势。具体分析这些数据泄露事件的发生原因&#xff0c;80%以上都是因为内…

【Python语言速回顾】——异常文件操作

目录 一、异常 1、检测异常try语句 2、抛出异常 3、异常处理流程 二、文件操作 1、打开文件 ①文件模式acess_mode ②文件缓冲区 2、基本的文件方法 ①读和写、关闭文件 ②读取行 ③文件重命名 ④删除文件&#xff08;系统中已存在的文件&#xff09; 3、基本的目…

[C++随想录] 二叉搜索树

搜素二叉树 二叉搜索树的使用二叉搜索树的模拟实现(K)整体结构循环版本递归版本 二叉搜索树的应用源码(kv) 二叉搜索树的使用 二叉搜索树 相较于 普通的二叉树来说: 根节点的左子树的所有键值都 小于 根节点, 根节点的右子树的所有键值 大于 根节点根节点的 左右子树 都是 二…

mac上mongodb 以及可视化工具 下载以及安装

简介 1. 下载 官网上的下载地址藏得非常深&#xff0c;不花老半天 根本找不到 下载地址 https://www.mongodb.com/try/download/community 目前最新社区版本7.0.2 下载链接 mac intel芯片 &#xff1a; https://fastdl.mongodb.org/osx/mongodb-macos-x86_64-7.0.2.tgz ma…

地面领域的“大疆”?通用足式机器人公司逐际动力获近2亿融资!

原创 | 文 BFT机器人 近日&#xff0c;通用足式机器人公司逐际动力完成天使轮和Pre-A轮融资&#xff0c;总金额近2亿元。逐际动力是一家通用足式机器人公司&#xff0c;成立于2022年&#xff0c;全球总部位于中国深圳&#xff0c;专注于运动智能&#xff08;Motion Intelligen…

html内连框架

src:引用页面地址 name&#xff1a;框架标识名称 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title> </head> <body> <!--iframe src&#xff1a;地址 w-h&#xff…

鸿鹄工程项目管理系统 Spring Cloud+Spring Boot+Mybatis+Vue+ElementUI+前后端分离构建工程项目管理系统项目背景

鸿鹄工程项目管理系统 Spring CloudSpring BootMybatisVueElementUI前后端分离构建工程项目管理系统 1. 项目背景 一、随着公司的快速发展&#xff0c;企业人员和经营规模不断壮大。为了提高工程管理效率、减轻劳动强度、提高信息处理速度和准确性&#xff0c;公司对内部工程管…

双十一必买好物,这四款好物你值得拥有

随着科技的不断发展&#xff0c;智能家电已经成为我们生活中不可或缺的一部分。在双十一期间&#xff0c;各大品牌都会推出各种优惠活动&#xff0c;以更优惠的价格购买到心仪的智能家电。比如智能超声波清洗机&#xff0c;智能门锁&#xff0c;它们不仅提高了我们的生活质量&a…