【数据结构】- 链表之单链表(下)

news2024/12/24 21:13:57

文章目录

  • 前言
  • 一、单链表(下)
    • 1.1 查找+修改
    • 1.2 在任意位置插入
      • 1.2.1 在pos位置插入(也就是pos位置之前)
      • 1.2.2 在pos位置之后插入
    • 1.3 在任意位置删除
      • 1.3.1 删除pos位置得值
      • 1.3.2 删除pos位置后面的值
  • 二、完整代码
  • 总结


前言

未来藏在迷雾中 叫人看来胆怯 带你踏足其中 就会云开雾散
本章是关于数据结构中的链表之单链表(下)


提示:以下是本篇文章正文内容,下面案例可供参考

一、单链表(下)

1.1 查找+修改

//SList.h
SLTNode* STFind(SLTNode* phead, SLTDataType x);
//SList.c
SLTNode* STFind(SLTNode* phead, SLTDataType x)
{
	SLTNode* cur = phead;
	while (cur)
	{
		if (cur->data == x)
		{
			return cur;
		}
		cur = cur->next;
	}
	return NULL;
}
//Test.c
void TestSList()
{
	SLTNode* plist = NULL;
	SLPushFornt(&plist, 1);
	SLPushFornt(&plist, 2);
	SLPushFornt(&plist, 3);
	SLPushFornt(&plist, 4);
	SLTPrint(plist);
	SLTNode* pos = STFind(plist, 3);
	if (pos)//判断是否为空
	{
		pos->data = 30;
	}
	SLTPrint(plist);
}

在这里插入图片描述

1.2 在任意位置插入

1.2.1 在pos位置插入(也就是pos位置之前)

//SList.h
void SLInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x);//在pos之前插入
//SList.c
void SLInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x)
{
	assert(pphead);
	assert(pos);
	if (*pphead == pos)
	{
		SLPushFornt(pphead, x);
	}
	else
	{
		SLTNode* prev = *pphead;
		while (prev->next != pos)
		{
			prev = prev->next;
		}
		SLTNode* newnode = BuyTNode(x);
		prev->next = newnode;
		newnode->next = pos;
	}
}
//Test.c
void TestSList()
{
	SLTNode* plist = NULL;
	SLPushFornt(&plist, 1);
	SLPushFornt(&plist, 2);
	SLPushFornt(&plist, 3);
	SLPushFornt(&plist, 4);
	SLTPrint(plist);
	SLTNode* pos = STFind(plist, 3);
	if (pos)//判断是否为空
	{
		SLInsert(&plist, pos, 30);
	}
}

流程图

  • 多个节点

在这里插入图片描述

  • 一个节点
    在这里插入图片描述

1.2.2 在pos位置之后插入

//SList.h
void SLInsertAfter(SLTNode* pos, SLTDataType x);//在pos之后插入
//SList.c
void SLInsertAfter(SLTNode* pos, SLTDataType x)
{
	assert(pos);
	SLTNode* newnode = BuyTNode(x);
	newnode->next = pos->next;
	pos->next = newnode;
}
//Test.c
void TestSList()
{
	SLTNode* plist = NULL;
	SLPushFornt(&plist, 1);
	SLPushFornt(&plist, 2);
	SLPushFornt(&plist, 3);
	SLPushFornt(&plist, 4);
	SLTPrint(plist);
	SLTNode* pos = STFind(plist, 2);
	if (pos)//判断是否为空
	{
		SLInsertAfter(pos, 30);
	}
	SLTPrint(plist);
}

流程图:
在这里插入图片描述
注意:
下面这种写法就存在了问题newnode指向了它自己造成了错误

void SLInsertAfter(SLTNode* pos, SLTDataType x)
{
	assert(pos);
	SLTNode* newnode = BuyTNode(x);
	pos->next=newnode;
	newnode->next=pos->next;
}

流程图:
在这里插入图片描述

1.3 在任意位置删除

1.3.1 删除pos位置得值

//SList.h
void SLErase(SLTNode** pphead, SLTNode* pos);
//SList.c
void SLErase(SLTNode** pphead, SLTNode* pos)
{
	assert(pphead);
	assert(pos);
	if (pos == *pphead)
	{
		SLPopFornt(pphead);//头删
	}
	else
	{
		SLTNode* prev = *pphead;
		while (prev->next != pos)
		{
			prev = prev->next;
		}
		prev->next = pos->next;
		free(pos);
	}
}
//Test.c
void TestSList()
{
	SLTNode* plist = NULL;
	SLPushFornt(&plist, 1);
	SLPushFornt(&plist, 2);
	SLPushFornt(&plist, 3);
	SLPushFornt(&plist, 4);
	SLTPrint(plist);
	SLTNode* pos = STFind(plist, 3);
	if (pos)//判断是否为空
	{
		SLErase(&plist, pos);
	}
	SLTPrint(plist);
}

流程图:
在这里插入图片描述

1.3.2 删除pos位置后面的值

//SList.h
void SLEraseAfter(SLTNode* pos);
//SList.c
void SLEraseAfter(SLTNode* pos)
{
	assert(pos);
	assert(pos->next);
	SLTNode* next = pos->next;
	pos->next = next->next;
	free(next);
}
//Test.c
void TestSList()
{
	SLTNode* plist = NULL;
	SLPushFornt(&plist, 1);
	SLPushFornt(&plist, 2);
	SLPushFornt(&plist, 3);
	SLPushFornt(&plist, 4);
	SLTPrint(plist);
		SLTNode* pos = STFind(plist, 3);
	if (pos)//判断是否为空
	{
		SLEraseAfter(pos);
	}
	SLTPrint(plist);
}

流程图:
在这里插入图片描述

二、完整代码

//SList.h
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>

typedef int SLTDataType;
typedef struct SListNode
{
	SLTDataType data;
	struct SListNode* next;
}SLTNode;

void SLTPrint(SLTNode* phead);
void SLPushFornt(SLTNode** pphead, SLTDataType x);
void SLPushBack(SLTNode** pphead, SLTDataType x);

void SLPopFornt(SLTNode** pphead);
void SLPopBack(SLTNode** pphead);


SLTNode* STFind(SLTNode* phead, SLTDataType x);

//任意位置插入
void SLInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x);//在pos之前插入
void SLInsertAfter(SLTNode* pos, SLTDataType x);//在pos之后插入
void SLErase(SLTNode** pphead, SLTNode* pos);//删除pos位置的值
void SLEraseAfter(SLTNode* pos);//删除pos位置的值





//SList.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"SList.h"

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

SLTNode* BuyTNode(SLTDataType x)
{
	SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
	if (newnode == NULL)
	{
		perror("malloc fail");
		return;
	}
	newnode->data = x;
	newnode->next = NULL;
	return newnode;
}

void SLPushFornt(SLTNode** pphead, SLTDataType x)
{
	SLTNode* newnode = BuyTNode(x);
	newnode->next  = *pphead;
	*pphead = newnode;
}

void SLPushBack(SLTNode** pphead, SLTDataType x)
{
	SLTNode* newnode = BuyTNode(x);
	//空链表
	if(*pphead==NULL)
	{
		*pphead = newnode;
	}
	//非空链表
	else
	{
		SLTNode* tail = *pphead;
		while (tail->next != NULL)
		{
			tail = tail->next;
		}
		tail->next = newnode;
	}
}

void SLPopFornt(SLTNode** pphead)
{
	//空链表
	assert(*pphead);
	//一个节点
	if ((*pphead)->next == NULL)
	{
		free(*pphead);
		*pphead = NULL;
	}
	//多个节点:保存下一个节点,释放当前节点
	else
	{
		SLTNode* del = *pphead;
		*pphead = del->next;
		free(del);
	}
}

void SLPopBack(SLTNode** pphead)
{
	//空链表
	assert(*pphead);
	//有一个节点
	if ((*pphead)->next == NULL)
	{
		free(*pphead);
		*pphead = NULL;
	}
	有多个节点
	else
	{
	SLTNode* prev = NULL;
	SLTNode* tail = *pphead;
	//找尾
	while (tail->next == NULL)//或者写成while(tail->next)
	{
		prev = tail;
		tail = tail->next;
	}
	free(tail);
	prev->next = NULL;
		while (tail->next->next != NULL)
		{
			tail = tail->next;
		}
		free(tail->next);
		tail->next = NULL;
	}
}

SLTNode* STFind(SLTNode* phead, SLTDataType x)
{
	SLTNode* cur = phead;
	while (cur)
	{
		if (cur->data == x)
		{
			return cur;
		}
		cur = cur->next;
	}
	return NULL;
}


void SLInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x)
{
	assert(pphead);
	assert(pos);
	if (*pphead == pos)
	{
		SLPushFornt(pphead, x);
	}
	else
	{
		SLTNode* prev = *pphead;
		while (prev->next != pos)
		{
			prev = prev->next;
		}
		SLTNode* newnode = BuyTNode(x);
		prev->next = newnode;
		newnode->next = pos;
	}
}

//在pos之后插入
void SLInsertAfter(SLTNode* pos, SLTDataType x)
{
	assert(pos);
	SLTNode* newnode = BuyTNode(x);
	newnode->next = pos->next;
	pos->next = newnode;
}

//删除pos位置的值
void SLErase(SLTNode** pphead, SLTNode* pos)
{
	assert(pphead);
	assert(pos);
	if (pos == *pphead)
	{
		SLPopFornt(pphead);//头删
	}
	else
	{
		SLTNode* prev = *pphead;
		while (prev->next != pos)
		{
			prev = prev->next;
		}
		prev->next = pos->next;
		free(pos);
	}
}

//删除pos位置后面的值
void SLEraseAfter(SLTNode* pos)
{
	assert(pos);
	assert(pos->next);
	SLTNode* next = pos->next;
	pos->next = next->next;
	free(next);
}




//Test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"SList.h"

void TestSList()
{
	SLTNode* plist = NULL;
	SLPushFornt(&plist, 1);
	SLPushFornt(&plist, 2);
	SLPushFornt(&plist, 3);
	SLPushFornt(&plist, 4);
	SLTPrint(plist);
	SLPushBack(&plist, 5);
	SLPopFornt(&plist);
	SLTPrint(plist);
	SLPopFornt(&plist);
	SLTPrint(plist);
	SLPopFornt(&plist);
	SLTPrint(plist);
	SLPopFornt(&plist);
	SLTPrint(plist);
	SLTNode* pos = STFind(plist, 3);
	if (pos)//判断是否为空
	{
		SLInsert(&plist, pos, 30);
	}
	SLTNode* pos = STFind(plist, 2);
	if (pos)//判断是否为空
	{
		SLInsertAfter(pos, 30);
	}
	SLTPrint(plist);
	SLTNode* pos = STFind(plist, 3);
	if (pos)//判断是否为空
	{
		SLErase(&plist, pos);
	}
	SLTPrint(plist);
	SLTNode* pos = STFind(plist, 3);
	if (pos)//判断是否为空
	{
		SLEraseAfter(pos);
	}
	SLTPrint(plist);
}


int main()
{
	TestSList();
	return 0;
}

总结

Ending,今天的链表之单链表(下)的内容就到此结束啦~,如果后续想了解更多,就请关注我吧,一键三连哦 ~

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

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

相关文章

【C++类和对象】类和对象(中):拷贝构造函数 {拷贝构造函数的概念及特征,拷贝构造函数不能使用传值传参,编译器自动生成的拷贝构造函数}

四、拷贝构造函数 4.1 概念 在创建对象时&#xff0c;可否创建一个与已存在对象一某一样的新对象呢&#xff1f; 拷贝构造函数&#xff1a;只有单个形参&#xff0c;该形参是对本类类型对象的引用(一般常用const修饰)&#xff0c;在用已存在的类类型对象创建新对象时由编译器…

MySQL高级(二)

一、SQL优化 &#xff08;一&#xff09;插入数据 批量插入 多次插入每一次insert都要与数据库建立连接。 INSERT INTO 表名 VALUES (),(),(); 一次插入数据不宜过多&#xff0c;不要超过1000条。 手动提交事务 START TRANSACTION; INSERT INTO 表名 VALUES (),(),(); I…

车载以太网 - SomeIP - 协议用例 - Format_01

目录 1、验证Client ID字段静态设置为0x0000 2、验证Session ID字段静态设置为0x0001 3、验证Protocol Version字段静态设置为0x01

SpringCloud:ElasticSearch之自动补全

当用户在搜索框输入字符时&#xff0c;我们应该提示出与该字符有关的搜索项&#xff0c;如图&#xff1a; 这种根据用户输入的字母&#xff0c;提示完整词条的功能&#xff0c;就是自动补全了。 因为需要根据拼音字母来推断&#xff0c;因此要用到拼音分词功能。 1.拼音分词器…

【移动端网页布局】移动端网页布局基础概念 ④ ( 物理像素 | 物理像素比 | 代码示例 - 100 像素在 PC浏览器 / 移动端浏览器 显示效果 )

文章目录 一、物理像素 / 物理像素比二、代码示例 - 100 像素在 PC浏览器 / 移动端浏览器 显示效果 一、物理像素 / 物理像素比 移动端 网页开发 与 PC 端开发有很多不同之处 , 在图片处理方向需要采用 二倍图 / 三倍图 / 多倍图 方式进行图片处理 ; 图片处理的方式与如下的 物…

项目支付接入支付宝【沙箱环境】

前言 订单支付接入支付宝&#xff0c;使用支付宝提供的沙箱机制模拟为订单付款。我这里主要记录一下沙箱环境如何接入到系统中&#xff0c;具体细节的实现。按照官方文档来就可以了。 1、使用步骤 这里有几个重要数据要拿到&#xff0c;一个是支付宝的公钥和私钥&#xff0c…

ClickHouse监控系统Prometheus+Grafana

目录 1 PrometheusGrafana概述2 安装Prometheus Grafana3 配置ClickHouse4 配置Grafana 1 PrometheusGrafana概述 ClickHouse 运行时会将一些个自身的运行状态记录到众多系统表中( system.*)。所以我们对于 CH 自身的一些运行指标的监控数据&#xff0c;也主要来自这些系统表。…

docoker笔记

0.安装Docker Docker 分为 CE 和 EE 两大版本。CE 即社区版&#xff08;免费&#xff0c;支持周期 7 个月&#xff09;&#xff0c;EE 即企业版&#xff0c;强调安全&#xff0c;付费使用&#xff0c;支持周期 24 个月。 Docker CE 分为 stable test 和 nightly 三个更新频道…

RabbitMQ【#1】是什么,有什么用

RabbiMQ是什么&#xff1f; RabbitMQ是一种开源的消息队列软件&#xff0c;它实现了高级消息队列协议&#xff08;AMQP&#xff09;并支持多种编程语言。它可以用于将消息从一个应用程序传递到另一个应用程序或进程&#xff0c;并支持分布式系统中的异步消息通信。RabbitMQ的主…

【Linux】System V 共享内存、消息队列、信号量

&#x1f34e;作者&#xff1a;阿润菜菜 &#x1f4d6;专栏&#xff1a;Linux系统编程 system V共享内存介绍 System V 共享内存是一种进程间通信的机制&#xff0c;它允许多个进程共享一块物理内存区域&#xff08;称为“段”&#xff09;。System V 共享内存的优点是效率高&…

AD21 PCB----过滤、捕获、板子边框绘制、精准移动

目录 过滤器和捕获 板子边框绘制 精准移动 过滤器和捕获 板子边框绘制 两种方式均在Mechanical 1 方式一&#xff1a; 第一步&#xff1a;利用PCB的基础图形进行绘制边框 第二步&#xff1a;选中绘制的图形 第三步&#xff1a; 方式二&#xff1a;外部导入 第一步&#x…

SpringCloud 微服务系列——【服务间的通信方式、OpenFeign、Hystrix组件使用】

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…

【UE 粒子系统】电火花粒子效果

效果 步骤 1. 新建一个粒子系统&#xff0c;命名为“SparkParticles” 再新建一个材质&#xff0c;命名为“SparkParticleMaterial” 2. 打开“SparkParticleMaterial”&#xff0c;将混合模式改为半透明&#xff0c;着色模型为无光照 然后添加如下节点 3. 打开“SparkParticl…

输入输出练习

文章目录 1. AB(1)2. AB(2)3. AB(3)4. AB(4)计算一系列数的和5. AB(5) 计算一系列数的和6. AB(6)7. AB(7)8. 字符串排序(1)9. 字符串排序(2)10 字符串排序(2)11. 注意数据范围 1. AB(1) import java.util.Scanner;// 注意类名必须为 Main, 不要有任何 package xxx 信息 public …

差分运算放大电路原理解析

差分运算放大电路&#xff0c;对共模信号得到有效抑制&#xff0c;而只对差分信号进行放大&#xff0c;因而得到广泛的用。 注&#xff1a; &#xff08;1&#xff09;共模信号   共模信号&#xff08;common mode signal&#xff09;是指同时作用于多个电路或电子设备上的信…

1.10和1.11和1.12、Makefile

1.10和1.11和1.12、Makefile 1.10、Makefile(1)1.10.1、什么是Makefile1.10.2、Makefile的文件命名和规则实际操作 1.11、Makefile(2)1. 工作原理&#xff08;1.10.3&#xff09;实际操作 1.12、Makefile(3)1. 变量2. 模式匹配3. 函数实际操作①实现变量和模式匹配②实现函数操…

Vue(简介、前期配置、Vue展示、模板语法)

一、简介 1. 什么是Vue&#xff1f; 2. Vue特点 采用组件化模式&#xff0c;提高代码复用率、且让代码更好维护 组件化&#xff1a;每一部分直接就是大盒子组件&#xff08;创建一个单独的Vue文件&#xff09;&#xff0c;直接可以修改单独封装的组件部分代码 Vue使用声明式…

为什么需要内网穿透技术?

随着互联网技术的快速发展&#xff0c;企业和个人越来越依赖于网络资源&#xff0c;而内网穿透技术正是解决远程访问内网资源的关键。本文将详细介绍内网穿透的概念及其重要性&#xff0c;以帮助您了解为什么我们需要使用内网穿透技术。 目录 一、内网穿透技术简介 二、为什…

Java中List排序的3种方法

在某些特殊的场景下&#xff0c;我们需要在 Java 程序中对 List 集合进行排序操作。比如从第三方接口中获取所有用户的列表&#xff0c;但列表默认是以用户编号从小到大进行排序的&#xff0c;而我们的系统需要按照用户的年龄从大到小进行排序&#xff0c;这个时候&#xff0c;…

2 变量运算符-基本数据类型讲解【Go语言教程】

2 变量运算符-基本数据类型讲解【Go语言教程】 2.1 变量 2.1.1 声明变量方式 指定变量类型&#xff0c;声明后若不赋值&#xff0c;使用默认值 类型推导 通过: 多变量声明 全局变量定义 在函数外部定义的就是全局变量 变量变量名值数据类型 注意&#xff1a;如果go程序报错&…