C语言之旅:探索单链表

目录

一、前言

二、实现链表的功能:

打印

创建节点

尾插

尾删

头插

头删

查找

在指定位置之前插入数据

指定位置删除

在指定位置之后插入数据

打印

销毁

三、全部源码: 

四、结语


一、前言

链表是一个强大且基础的数据结构。对于很多初学者来说,链表可能是一个令人望而生畏的主题,因为它涉及到了动态内存分配和指针操作等较为高级的概念。但是,一旦你掌握了链表的基本概念和操作,你会发现它在很多实际应用中都有着广泛的应用。

今天,我们就从C语言的角度,来探索一下单链表的基本概念和实现方法。在接下来的篇幅中,我将带你逐步构建一个单链表的简单实现,并解释其中的关键概念和代码逻辑。 

首先,我们需要明确什么是单链表。单链表是一种线性数据结构,它的元素(在C语言中通常称为节点)按照线性的顺序排列,但每个节点并不是在内存中连续存储的。相反,每个节点都包含两个部分:一个是数据域(用于存储实际的数据),另一个是指针域(用于指向下一个节点)。通过这种方式,我们可以将多个节点连接起来,形成一个链状的数据结构。

单链表的定义:
 

typedef int 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);

打印

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

创建节点

SLTNode* SLTBuyNode(SLTDataType x) 
{SLTNode* newNode = (SLTNode*)malloc(sizeof(SLTNode));if (newNode == NULL) {perror("malloc fail!");exit(1);}newNode->data = x;newNode->next = NULL;return newNode;
}

尾插

void SLTPushBack(SLTNode** pphead, SLTDataType x) 
{SLTNode* newNode = SLTBuyNode(x);// 如果链表为空,直接让头指针指向新节点  if (*pphead == NULL) {*pphead = newNode;return;}// 否则,找到链表尾部并插入新节点  SLTNode* current = *pphead;while (current->next != NULL){current = current->next;}current->next = newNode;
}

尾删

//尾删
void SLTPopBack(SLTNode** pphead)
{assert(pphead && *pphead);SLTNode* prev = NULL;SLTNode* current = *pphead;while (current->next != NULL){prev = current;current = current->next;}free(current);if (prev == NULL){*pphead = NULL;}else{prev->next = NULL;}
}

1.  首先,检查传入的二级指针和其指向的头指针是否为空,以确保链表存在。
2.  接着,定义了两个指针prev和current,用于遍历链表并找到尾节点。
在循环中,prev总是指向current的前一个节点,而current则遍历链表直到找到尾节点(即current->next为NULL的节点)。
3.  找到尾节点后,释放其内存。
4.  最后,根据prev是否为空来判断链表是否只有一个节点。如果是,则将头指针置为NULL;否则,将prev的next指针置为NULL,完成尾节点的删除。 

头插

//头插
void SLTPushFront(SLTNode** pphead, SLTDataType x)
{assert(pphead);SLTNode* newNode = SLTBuyNode(x);newNode->next = *pphead;*pphead = newNode;}

我们首先通过断言确保传入的二级指针pphead不为空。接着,我们调用SLTBuyNode函数来根据给定的数据x创建一个新的节点newNode。然后,我们将新节点的next指针设置为当前的头节点*pphead,这样新节点就连接到了链表的开始位置。最后,我们更新头指针*pphead,使其指向新节点,从而完成了在链表头部插入新节点的操作。 

头删

//头删
void SLTPopFront(SLTNode** pphead)
{assert(pphead && *pphead);SLTNode* tmp = (*pphead)->next;free(*pphead);*pphead=tmp;
}

定义一个临时指针tmp,让它指向当前头节点的下一个节点。接着,我们释放当前头节点的内存。最后,我们更新头指针*pphead,使其指向tmp, 从而完成了头节点的删除操作。如果链表原本只有一个节点,那么删除后头指针*pphead将被设置为NULL,表示链表为空。

查找

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

使用一个指针pcur来遍历链表,从头节点开始,逐个检查每个节点的数据是否与要查找的数据x相等。如果找到了匹配的节点,就返回该节点的指针;如果遍历完整个链表都没有找到匹配的节点,则返回NULL表示未找到。

在指定位置之前插入数据

void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x)
{assert(pphead && *pphead);assert(pos);SLTNode* newnode = SLTBuyNode(x);if (pos == *pphead){SLTPushFront(pphead, x);}else{// 找到pos节点的前一个节点  SLTNode* prev = *pphead;while (prev->next != pos){prev = prev->next;}// 在pos之前插入新节点  newnode->next = pos;prev->next = newnode;}
}

指定位置删除

void SLTErase(SLTNode** pphead, SLTNode* pos)
{assert(pphead && *pphead);assert(pos);if (pos == *pphead){*pphead = pos->next;}else{SLTNode* prev = *pphead;while (prev->next != pos)// 遍历链表,找到要删除节点的前一个节点{prev = prev->next;}prev->next = pos->next;}}

在指定位置之后插入数据

//在指定位置之后插入数据
void SLTInsertAfter(SLTNode* pos, SLTDataType x)
{assert(pos);SLTNode* newnode = SLTBuyNode(x);newnode->next = pos->next;pos->next = newnode;}

设置新节点的next指针指向pos的下一个节点。最后,它将pos的next指针指向新节点,从而将新节点插入到pos之后。 

打印

//打印
void SLPrint(SL* ps)
{for (int i = 0; i < ps->size; i++) {printf("%d ", ps->arr[i]);}printf("\n");
}

销毁

//销毁
void SListDesTroy(SLTNode** pphead)
{assert(pphead && *pphead);SLTNode* pcur = *pphead;while (pcur != NULL){SLTNode* next = pcur->next;free(pcur);pcur = next;}*pphead = NULL;
}

三、全部源码: 

// 打印链表
void SLTPrint(SLTNode* phead)
{SLTNode* pucr = phead;while (pucr != NULL){printf("%d->", pucr->data);pucr = pucr->next;}printf("NULL\n");
}
//初始化
SLTNode* SLTBuyNode(SLTDataType x) 
{SLTNode* newNode = (SLTNode*)malloc(sizeof(SLTNode));if (newNode == NULL) {perror("malloc fail!");exit(1);}newNode->data = x;newNode->next = NULL;return newNode;
}
// 尾部插入  
void SLTPushBack(SLTNode** pphead, SLTDataType x) 
{SLTNode* newNode = SLTBuyNode(x);// 如果链表为空,直接让头指针指向新节点  if (*pphead == NULL) {*pphead = newNode;return;}// 否则,找到链表尾部并插入新节点  SLTNode* current = *pphead;while (current->next != NULL){current = current->next;}current->next = newNode;
}
//尾删
void SLTPopBack(SLTNode** pphead)
{assert(pphead && *pphead);SLTNode* prev = NULL;SLTNode* current = *pphead;while (current->next != NULL){prev = current;current = current->next;}free(current);if (prev == NULL){*pphead = NULL;}else{prev->next = NULL;}
}//头插
void SLTPushFront(SLTNode** pphead, SLTDataType x)
{assert(pphead);SLTNode* newNode = SLTBuyNode(x);newNode->next = *pphead;*pphead = newNode;}
//头删
void SLTPopFront(SLTNode** pphead)
{assert(pphead && *pphead);SLTNode* tmp = (*pphead)->next;free(*pphead);*pphead=tmp;
}
//查找
SLTNode* SLTFind(SLTNode* phead, SLTDataType x)
{SLTNode* pcur = phead;while (pcur != NULL){if (pcur->data == x){return pcur;}pcur = pcur->next;}return NULL;
}
//在指定位置之前插入数据
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x)
{assert(pphead && *pphead);assert(pos);SLTNode* newnode = SLTBuyNode(x);if (pos == *pphead){SLTPushFront(pphead, x);}else{// 找到pos节点的前一个节点  SLTNode* prev = *pphead;while (prev->next != pos){prev = prev->next;}// 在pos之前插入新节点  newnode->next = pos;prev->next = newnode;}
}
//删除pos节点
void SLTErase(SLTNode** pphead, SLTNode* pos)
{assert(pphead && *pphead);assert(pos);if (pos == *pphead){*pphead = pos->next;}else{SLTNode* prev = *pphead;while (prev->next != pos){prev = prev->next;}prev->next = pos->next;}}
//在指定位置之后插入数据
void SLTInsertAfter(SLTNode* pos, SLTDataType x)
{assert(pos);SLTNode* newnode = SLTBuyNode(x);newnode->next = pos->next;pos->next = newnode;}//删除pos之后的节点
void SLTEraseAfter(SLTNode* pos)
{assert(pos&&pos->next);SLTNode* del = pos->next;pos->next = del->next;free(del);del = NULL;	}
//销毁链表
void SListDesTroy(SLTNode** pphead)
{assert(pphead && *pphead);SLTNode* pcur = *pphead;while (pcur != NULL){SLTNode* next = pcur->next;free(pcur);pcur = next;}*pphead = NULL;
}

四、结语

总之,C语言中的单链表之旅是一次富有成效的学习经历。它不仅让我们掌握了链表的基本操作,还提高了我们的编程技能和问题解决能力。希望这个旅程能为你在数据结构和算法领域的进一步探索打下坚实的基础。

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

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

相关文章

禁用手机连接 - Win11

问题 Win11系统自带手机连接软件&#xff0c;会在后台自启&#xff0c;不适用于全部的手机型号&#xff0c;而且常规方法无法卸载。甚至任务管理器中&#xff0c;此软件的后台进程高达76个&#xff0c;如下图。下文以Win11系统为例&#xff0c;介绍如何禁用手机连接。 解决方…

考研数学:有些无穷小不能用等价无穷小的公式?

今天要给大家分享的笔记是&#xff1a;《有些无穷小虽然是无穷小&#xff0c;但却不能用无穷小的相关公式》&#xff1a;

来自大厂硬盘的降维打击!当希捷酷玩520 1TB SSD卷到369,请问阁下该怎么应对?

来自大厂硬盘的降维打击&#xff01;当希捷酷玩520 1TB SSD卷到369&#xff0c;请问阁下该怎么应对&#xff1f; 哈喽小伙伴们好&#xff0c;我是Stark-C~ 今年4月份的时候因为电脑上的游戏盘突然挂掉&#xff0c;为了性价比选购了希捷酷玩520 1TB SSD&#xff0c;同时我也是…

7. MySQL 视图、索引

文章目录 【 1. 视图 View 】1.1 视图原理1.2 创建视图 CREATE VIEW1.2.1 创建基于单表的视图1.2.2 创建基于多表的视图 1.3 查看视图1.3.1 查看视图的内容1.3.2 查看视图的详细信息 1.4 修改视图 ALTER VIEW1.4.1 修改视图内容1.4.2 修改视图名称 1.5 删除视图 DORP VIEW 【 2…

961题库 北航计算机 计算机网络 附答案 选择题形式

有题目和答案&#xff0c;没有解析&#xff0c;不懂的题问大模型即可&#xff0c;无偿分享。 第1组 习题 OSI 参考模型的第 5 层( 自下而上 ) 完成的主要功能是 A. 差错控制 B. 路由选择 C. 会话管理 D. 数据表示转换 100BaseT 快速以太网使用的导向传输介质是 A. 双绞线 B. …

Gin的快速入门和搭建

文章目录 Go的工程工程架构技术选型 Gin入门 Go的工程 基于Go生态&#xff0c;构建一个支持内容管理&#xff0c;内容加工、内容分发的内容库系统。 内容管理&#xff1a;增删改查内容加工&#xff1a;例如内容审核、推荐等内容分发&#xff1a;将内容可以推到不同的业务线 …

linux进阶的一些操作以及知识点------习题集(实践)

请创建以你姓名全拼的用户luwenhua&#xff0c;将其设置为免密登录&#xff0c;切换到luwenhua用户&#xff0c;打开终端&#xff0c;完成以下操作 &#xff08;一&#xff09;bash脚本基础练习 1&#xff09;第一题&#xff1a;请在终端里定义两个用户变量num120&#xff0c…

C# try catch异常捕获

异常捕获 执行过程&#xff1a;try中的代码没有出现异常&#xff0c;则catch里面不会自行&#xff0c;如果try中代码出现异常&#xff0c;则后面的代码都不执行&#xff0c;直接跳到catch中的代码执行。 // try catch 可以捕获多个错误&#xff0c; try...catch...catch.... …

C++一个StringBad类

设计一个字符串类,下面的代码是一个不好的设计,起名StringBad。 //stringbad.h #pragma once //一个设计有问题的string类 #include <iostream> using namespace std;class StringBad { public:StringBad();//默认构造函数StringBad(const char* s);//构造函数~StringBa…

计算机毕业设计 | springboot+vue会议室管理系统(附源码)

1&#xff0c;绪论 1.1 项目背景 随着企业规模的不断扩大&#xff0c;会议室管理愈加复杂。传统的手工预约会议室的方式已经无法满足现代企业的需求&#xff0c;因此&#xff0c;开发一套会议室系统方案变得尤为重要。会议室系统可以实现会议室的在线预约、会议室资源的有效利…

【TB作品】MSP430 G2553 单片机口袋板,电风扇模拟控制系统设计

功能 电风扇模拟控制系统设计 基本要求: 用LED/LCD 显示电风扇的工作状态 (1,2,3,4 四档风力), 显示风类:“自然风”、“常风”和“睡眠风”。 设计 “自然风”“常风”和“睡眠风” 三个风类键用于设置风类 设计一个“摇头”键用于控制电机摇头。 设计一个“定时”键&#x…

慢SQL的治理思路

慢SQL的治理思路 什么是慢SQL慢SQL产生的原因查看慢 SQL 是否开启开启慢 SQL 记录开启慢查询日志分析慢 SQL解决和优化慢SQL的方法 什么是慢SQL 慢 SQL 指的是 MySQL 中执行比较慢的 SQL&#xff0c;排查慢 SQL 最常用的方法是通过慢查询日志来查找慢 SQL。 MySQL 的慢查询日志…

快速排序与归并排序(非递归)

目录 快速排序&#xff08;双指针法&#xff09; 原理 代码 快速排序&#xff08;非递归&#xff09; 原理 代码 归并排序 介绍 优点 缺点 图片 原理 代码 归并排序&#xff08;非递归&#xff09; 代码 快速排序&#xff08;双指针法&#xff09; 快速排序的精…

2024年06月编程语言流行度排名

点击查看最新编程语言流行度排名&#xff08;每月更新&#xff09; 2024年06月编程语言流行度排名 编程语言流行度排名是通过分析在谷歌上搜索语言教程的频率而创建的 一门语言教程被搜索的次数越多&#xff0c;大家就会认为该语言越受欢迎。这是一个领先指标。原始数据来自…

【30天精通Prometheus:一站式监控实战指南】第15天:ipmi_exporter从入门到实战:安装、配置详解与生产环境搭建指南,超详细

亲爱的读者们&#x1f44b;   欢迎加入【30天精通Prometheus】专栏&#xff01;&#x1f4da; 在这里&#xff0c;我们将探索Prometheus的强大功能&#xff0c;并将其应用于实际监控中。这个专栏都将为你提供宝贵的实战经验。&#x1f680;   Prometheus是云原生和DevOps的…

(奇幻森林)POLYGON - Enchanted Forest - Nature Biomes - 3D Environment Art by Synty

各种雄伟的树木,装饰着优雅简化的树叶,在头顶形成了一个天堂般的树冠,在苔藓覆盖的森林地面上投下了宁静的咒语。 每一项资产,从引人入胜的环境材料到平缓的波浪状山丘,都经过精心制作,将您带到魔法和自然融合的地方。POLYGON-魔法森林-自然生物技术为数字领域注入真正魔…

60 关于 SegmentFault 的一些场景 (2)

前言 呵呵 此问题主要是来自于 帖子 月经结贴 -- 《Segmentation Fault in Linux》 这里主要也是 结合了作者的相关 case, 来做的一些 调试分享 当然 很多的情况还是 蛮有意思 本文主要问题如下 1. 访问异常堆栈地址1 2. 访问异常堆栈地址2 3. 访问异常堆栈地址3 4. sta…

第三届大湾区算力大会丨暴雨开启数字未来新篇

5月30-31日&#xff0c;韶关市迎来主题为“算启新篇智创未来”的第三届粤港澳大湾区(广东)算力产业大会暨第二届中国算力网大会&#xff0c;活动由广东省人民政府主办&#xff0c;广东省政数局、韶关市人民政府共同承办。暴雨信息作为算力产业发展的重要构建者受邀赴会&#xf…

Java的数据库编程-----JDBC

目录 一.JDBC概念&使用条件&#xff1a; 二.mysql-connector驱动包的下载与导入&#xff1a; 三.JDBC编程&#xff1a; 使用JDBC编程的主要五个步骤&#xff1a; 完整流程1&#xff08;更新update&#xff09;&#xff1a; 完整流程2(查询query)&#xff1a; 一.JDB…

汪小菲直播翻车亲儿子直言麻六记有异味网友热议引爆话题

汪小菲直播翻车&#xff01;亲儿子直言“麻六记”有“异味”&#xff0c;网友热议引爆话题在星光璀璨的娱乐圈&#xff0c;汪小菲一直以家庭幸福、事业有成的形象示人。然而&#xff0c;近日的一场直播让他遭遇了前所未有的尴尬。在直播中&#xff0c;汪小菲兴致勃勃地向观众跨…