[C语言][数据结构][链表] 单链表的从零实现!

news2024/10/6 14:27:24

目录

零.必备知识

1.一级指针 && 二级指针

2. 节点的成员列表

    a.数据

    b.指向下一个节点的指针.

3. 动态内存空间的开辟 (malloc-calloc-realloc)

一.单链表的实现与销毁 

        1.1 节点的定义

        1.2 单链表的尾插

        1.3 单链表的头插

        1.4 单链表的尾删

        1.5 单链表的头删 

        1.6 单链表的查找

        1.7 在指定位置之前插入数据

        1.8 在指定位置之后插入数据

        1.9 删除指定位置的数据

        1.10 删除指定位置之后的数据

        1.11 销毁单链表 

二. 单链表源码

SingleList.h

SingleList.c 


零.必备知识

1.一级指针 && 二级指针

2. 节点的成员列表

    a.数据

    b.指向下一个节点的指针.

3. 动态内存空间的开辟 (malloc-calloc-realloc)


一.单链表的实现与销毁 

注:具体解释都在代码的注释中!(在代码中具体分析)

        1.1 节点的定义

        1.2 单链表的尾插

 

        1.3 单链表的头插

 

        1.4 单链表的尾删

        1.5 单链表的头删 

        1.6 单链表的查找

        1.7 在指定位置之前插入数据

        1.8 在指定位置之后插入数据

        

 

        1.9 删除指定位置的数据

        1.10 删除指定位置之后的数据

        1.11 销毁单链表 

二. 单链表源码

SingleList.h

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

// 节点的定义
typedef int SLTDateType;
typedef struct SingleListNode
{
	SLTDateType date;
	struct SingleListNode* next;
}SLTNode;

// 单链表的展示
void SLTPrint(SLTNode* phead);
// 单链表的尾插
void SLTPushBack(SLTNode** pphead, SLTDateType x);
// 单链表的头插
void SLTPushFront(SLTNode** pphead, SLTDateType x);
// 单链表的尾删
void SLTPopBack(SLTNode** pphead);
// 单链表的头删
void SLTPopFront(SLTNode** pphead);
// 单链表的查找
SLTNode* SLTFind(SLTNode* phead, SLTDateType x);
// 在指定位置之前插入数据
void SLTInsertBefore(SLTNode** pphead, SLTNode* pos, SLTDateType x);
// 在指定位置之后插入数据
void SLTInsertAfter(SLTNode** pphead, SLTNode* pos, SLTDateType x);
// 删除指定位置的数据
void SLTErase(SLTNode** pphead, SLTNode* pos);
// 删除指定位置之后的数据
void SLTEraseAfter(SLTNode** pphead, SLTNode* pos);
// 销毁单链表
void SLTDestroy(SLTNode** pphead);

SingleList.c 

#define  _CRT_SECURE_NO_WARNINGS
#include "SingleList.h"
// 单链表的展示
void SLTPrint(SLTNode* phead)
{
	SLTNode* pcur = phead; //current 当前的,现在的  currect 正确的
	while (pcur != NULL) {
		printf("%d->", pcur->date);
		pcur = pcur->next;
	}
	printf("NULL\n");
}
// 节点的创造
SLTNode* SLTCreat(SLTDateType x)
{
	SLTNode* newNode = (SLTNode*)malloc(sizeof(SLTNode));
	if (newNode == NULL) {
		printf("创建失败!\n");
		exit(1);
	}
	newNode->date = x;
	newNode->next = NULL;
	return newNode;
}
// 单链表的尾插
void SLTPushBack(SLTNode** pphead, SLTDateType x)
{
	assert(pphead);
	// 创建节点
	SLTNode* newNode = SLTCreat(x);
	// 没有节点
	if ((*pphead) == NULL) {
		(*pphead) = newNode;
	}
	else { // 有一个或多个节点
		SLTNode* pcur = (*pphead);
		while (pcur->next != NULL) {
			pcur = pcur->next;
		}
		pcur->next = newNode;
	}
}
// 单链表的头插
void SLTPushFront(SLTNode** pphead, SLTDateType x)
{
	assert(pphead);
	SLTNode* pcur = (*pphead);
	// 创建节点
	SLTNode* newNode = SLTCreat(x);
	// 没有节点
	if ((*pphead) == NULL) {
		(*pphead) = newNode;
	}
	else { // 有一个或者多个节点
		newNode->next = (*pphead);
		(*pphead) = newNode;
	}
}
// 单链表的尾删
void SLTPopBack(SLTNode** pphead)
{
	assert(pphead && (*pphead));
	SLTNode* pcur = (*pphead);
	SLTNode* prev = (*pphead);
	// 只有一个节点
	if (pcur->next == NULL) {
		free(*pphead);
		(*pphead) = NULL;
		pcur = NULL;
		prev = NULL;
	}
	else { // 有多个节点
		while (pcur->next != NULL) {
			prev = pcur;
			pcur = pcur->next;
		}
		free(pcur);
		pcur = NULL;
		prev->next = NULL;
	}
}
// 单链表的头删
void SLTPopFront(SLTNode** pphead)
{
	assert(pphead && (*pphead));
	SLTNode* pcur = (*pphead);
	// 只有一个节点
	if (pcur->next == NULL) {
		free(*pphead);
		(*pphead) = NULL;
		pcur = NULL;
	}
	else { //有多个节点
		(*pphead) = (*pphead)->next;
		free(pcur);
		pcur = NULL;
	}
}
// 单链表的查找
SLTNode* SLTFind(SLTNode* phead, SLTDateType x)
{
	SLTNode* pcur = phead;
	while (pcur != NULL) {
		if (pcur->date == x) {
			printf("找到了!\n");
			return pcur;
		}
		pcur = pcur->next;
	}
	printf("找不到!\n");
	return NULL;
}
// 在指定位置之前插入数据
void SLTInsertBefore(SLTNode** pphead, SLTNode* pos, SLTDateType x)
{
	assert(pphead);
	SLTNode* pcur = (*pphead);
	// 创建节点
	SLTNode* newNode = SLTCreat(x);
	// 头插
	if (pos == (*pphead) || (*pphead) == NULL) {
		SLTPushFront(pphead, x);
	}
	else { //正常插入
		while (pcur->next != NULL) {
			if (pcur->next == pos) {
				newNode->next = pcur->next;
				pcur->next = newNode;
				break;
			}
			pcur = pcur->next;
		}
	}
}
// 在指定位置之后插入数据
void SLTInsertAfter(SLTNode** pphead, SLTNode* pos, SLTDateType x)
{
	assert(pphead);
	// 创建节点
	SLTNode* newNode = SLTCreat(x);
	if ((*pphead) == NULL || pos == (*pphead)) {
		// 尾插
		SLTPushBack(pphead, x);
	}
	else { //正常插入
		SLTNode* pcur = (*pphead);
		while (pcur->next != NULL) {
			if (pcur == pos) {
				newNode->next = pcur->next;
				pcur->next = newNode;
				break;
			}
			pcur = pcur->next;
		}
	}
}
// 删除指定位置的数据
void SLTErase(SLTNode** pphead, SLTNode* pos)
{
	assert(pphead && (*pphead));
	// 处理特殊情况(头删)
	if ((*pphead) == pos) {
		SLTPopFront(pphead);
	}
	else {
		SLTNode* prev = (*pphead);
		SLTNode* pcur = (*pphead);
		while (pcur != NULL) {
			if (pcur == pos) {
				prev->next = pcur->next;
				free(pcur);
				pcur = NULL;
				prev = NULL;
				break;
			}
			prev = pcur;
			pcur = pcur->next;
		}
	}
}
// 删除指定位置之后的数据
void SLTEraseAfter(SLTNode** pphead, SLTNode* pos)
{
	assert(pphead && (*pphead));
	SLTNode* pcur = (*pphead);
	while (pcur->next != NULL) {
		if (pcur == pos) {
			SLTNode* tmp = pcur->next;
			pcur->next = pcur->next->next;
			free(tmp);
			tmp = NULL;
			break;
		}
		pcur = pcur->next;
	}
}
// 销毁单链表
void SLTDestroy(SLTNode** pphead)
{
	assert(pphead && (*pphead));
	SLTNode* pcur = (*pphead);
	SLTNode* prev = (*pphead);
	while (pcur != NULL) {
		prev = pcur;
		pcur = pcur->next;
		free(prev);
	}
	prev = NULL;
	(*pphead) = NULL;
}

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

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

相关文章

Harmony鸿蒙南向驱动开发-RTC

RTC&#xff08;real-time clock&#xff09;为操作系统中的实时时钟设备&#xff0c;为操作系统提供精准的实时时间和定时报警功能。当设备下电后&#xff0c;通过外置电池供电&#xff0c;RTC继续记录操作系统时间&#xff1b;设备上电后&#xff0c;RTC提供实时时钟给操作系…

第十四届蓝桥杯真题-平方差

考察(数学应用) 代码及其解析:90%数据 #include <iostream> using namespace std; int main() {int ans0;long long a,b;cin>>a>>b;for(int ia;i<b;i){if(i%21)ans;if(i%40)ans; }cout<<ans;return 0; }

一例简单的文件夹病毒的分析

概述 这是一个典型的文件夹病毒&#xff0c;使用xp时代的文件夹图标&#xff0c;通过可移动存储介质传播&#xff0c;会向http://fionades.com/ABIUS/setup.exe下载恶意载荷执行。 其病毒母体只是一个加载器&#xff0c;会在内存是解密加载一个反射型的dll&#xff0c;主要的…

uniapp - 微信小程序 - 使用uCharts的一些问题

文章目录 uniapp - 微信小程序 - 使用uCharts的一些问题一、开发者工具显示正常&#xff0c;真机调试统计图不随页面滚动二、数据过多开启滚动条&#xff0c;无法滑动滚动条三、饼图点击不显示提示窗/点击位置bug、多个同类型统计图点击不显示提示框问题四、 formatter 自定义 …

九州金榜|孩子叛逆期仇视父母怎么办?

孩子在成长到一段阶段就会出现叛逆&#xff0c;孩子出现了叛逆情绪&#xff0c;如果家长处理不好亲子关系&#xff0c;孩子很容易仇视父母&#xff0c;这对于家长来说是非常心痛的&#xff0c;在这个阶段的孩子对父母来说&#xff0c;具有一定挑战性&#xff0c;这也是引导孩子…

基于单片机电子指南针系统设计

**单片机设计介绍&#xff0c;基于单片机电子指南针系统设计 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于单片机电子指南针系统设计概要主要涵盖了硬件设计、软件设计、磁场传感器选择、数据处理和显示等方面。以下是对该…

【MySQL数据库 | 第二十五篇】深入探讨MVCC底层原理

前言&#xff1a; 在当今互联网时代&#xff0c;数据库扮演着数据存储和管理的关键角色。对于大型Web应用程序和企业级系统而言&#xff0c;高效地处理并发访问和事务管理是至关重要的。多版本并发控制&#xff08;MVCC&#xff09;是一种数据库事务处理的技术&#xff0c;旨…

【数据结构练习题】队——1.用队实现栈2.用栈实现队

♥♥♥♥♥个人主页♥♥♥♥♥ ♥♥♥♥♥数据结构练习题总结专栏♥♥♥♥♥ ♥♥♥♥♥上一章&#xff1a;堆的练习题♥♥♥♥♥ 文章目录 1.用队去实现栈1.1问题描述1.2思路分析1.3绘图分析1.4代码实现2.用栈实现队2.1问题描述2.2思路分析1.3绘图分析2.4代码实现 1.用队去实现…

doss攻击为什么是无解的?

这个让Google、亚马逊等实力巨头公司也无法避免的攻击。可以这么说&#xff0c;是目前最强大、最难防御的攻击之一&#xff0c;属于世界级难题&#xff0c;并且没有解决办法。 Doss攻击的原理不复杂&#xff0c;就是利用大量肉鸡仿照真实用户行为&#xff0c;使目标服务器资源…

【漏洞复现】WordPress Welcart 任意文件读取漏洞(CVE-2022-4140)

0x01 产品简介 Welcart 是一款免费的 WordPress 电子商务插件。Welcart 具有许多用于制作在线商店的功能和自定义设置。您可以轻松创建自己的原始在线商店。 0x02 漏洞概述 Welcart存在任意文件读取漏洞&#xff0c;未授权的攻击者可以通过该漏洞读取任意文件&#xff0c;获…

【无标题】系统思考—心智模式

“直到你使无意识变为有意识&#xff0c;它将指导你的生活并且你会称之为命运。”—卡尔荣格 心智模式深藏于我们内心之中&#xff0c;它潜移默化地影响着我们对世界的理解和判断。往往这些影响是如此隐蔽&#xff0c;以至于我们自己都未必察觉到是什么在驱动我们的选择、决策…

利用Python ARM网关仓储物流AGV小车控制器

在现代智慧物流体系中&#xff0c;高效的信息管理系统是物流中心实现精准跟踪货物、科学管理库存及优化配送路线的关键环节。通过采用ARM架构的工控机或网关&#xff0c;并结合Python的二次开发能力&#xff0c;可以有效集成并强化物流管理系统的数据处理与通信功能&#xff0c…

最坏情况为线性时间的第k大元素

在统计和数据分析中&#xff0c;我们经常会遇到求最大值、最小值、中位数、四分位数、Top K等类似需求&#xff0c;其实它们都属于顺序统计量&#xff0c;本文将对顺序统计量的定义和求解算法进行介绍&#xff0c;重点介绍如何在最差时间复杂度也是线性的情况下求解第k大元素。…

代码随想录:栈与队列4-6

20.有效的括号 题目 给定一个只包括 (&#xff0c;)&#xff0c;{&#xff0c;}&#xff0c;[&#xff0c;] 的字符串 s &#xff0c;判断字符串是否有效。 有效字符串需满足&#xff1a; 左括号必须用相同类型的右括号闭合。左括号必须以正确的顺序闭合。每个右括号都有一…

OpenHarmony分布式软总线API调用测试工具 softbus_tool使用说明

softbus_tool 是 OpenHarmony 分布式软总线 API 调用测试工具&#xff0c;文件结构如下图所示。 softbus_tool 能够将软总线 interfaces 目录下的一些常用接口集中起来&#xff0c;供设备间搭建一些场景时使用&#xff08;比如设备绑定、BR 组网&#xff0c;BLE 组网&#xff…

红豆Cat 1开源|项目三: 从0-1设计一款HTTP版本RTU(支持GNSS)产品的软硬件全过程

HTTP版RTU&#xff08;支持GNSS&#xff09;项目概述 RTU&#xff08;Remote Terminal Unit&#xff09;&#xff0c;中文即远程终端控制系统&#xff0c;负责对现场信号、工业设备的监测和控制。RTU是构成企业综合自动化系统的核心装置&#xff0c;通常由信号输入/出模块、微…

ArrayList中多线程的不安全问题

ArrayList中的不安全问题 正常的输出 List<String> list Arrays.asList("1","2","3"); list.forEach(System.out::println);为什么可以这样输出&#xff0c;是一种函数是接口&#xff0c;我们先过个耳熟 Arrys.asList是返回一个ArrayL…

Redis高级-分布式缓存RDB原理

分布式缓存 1.1.2.RDB原理 bgsave开始时会fork主进程得到子进程&#xff0c;子进程共享主进程的内存数据。完成fork后读取内存数据并写入 RDB 文件。 fork采用的是copy-on-write技术&#xff1a; 当主进程执行读操作时&#xff0c;访问共享内存&#xff1b;当主进程执行写操…

振弦式应变计在岩土工程中的应用

岩土工程是土木工程的一个重要分支&#xff0c;主要研究岩石、土壤等天然材料的工程特性及其在工程中的应用。它涉及地基基础、边坡工程、隧道工程、水利水电工程等众多领域&#xff0c;是保障建筑物安全、稳定的基础性工程。 点击输入图片描述&#xff08;最多30字&#xff09…

rabbitmq延迟队列的使用

rabbitmq延迟队列的使用 1、场景&#xff1a; 1.定时发布文章 2.秒杀之后&#xff0c;给30分钟时间进行支付&#xff0c;如果30分钟后&#xff0c;没有支付&#xff0c;订单取消。 3.预约餐厅&#xff0c;提前半个小时发短信通知用户。 A -> 13:00 17:00 16:30 延迟时间&a…