链表的一步步实现(需有一部分c语言基础)【缓慢更新中

news/2024/12/12 13:25:32/文章来源:https://www.cnblogs.com/WisdomWu/p/18599036

链表的一步步实现(需有一部分c语言基础)

(由于本人上课实在没学懂链表的具体实现步骤,于是写下这篇博客记录学习过程,有兴趣的新手也可以跟着学习

1.认识链表的结构&创建简单静态链表并输出数据

Q:什么是链表?

A:链表是由一系列节点组成,每个节点包含两个域,一个是数据域,用来保存数据,另外一个是指针域,保存下一个节点的地址,链表在内存是非连续的。简单来说,链表就是结构体变量与结构体变量通过指针连接在一起。

[注]:该图中一个大长方形表示为链表中的一个元素,即一个节点;一个大长方形由两个小长方形组成,分别表示节点的数据(图中黄色高亮),和指向下一个节点的指针(图中红色高亮)。

Q:为什么要使用链表?
A:链表在指定位置插入和删除不像数组那样需要移动大量元素,只需要修改对应位置的指针即可。比如如果我要把一个元素b插入a[10]这个数组的第五位,那么从a[5]开始到a[9],所有的元素都要向后移动一位,非常麻烦。而链表只需要修改原先第四位和第五位节点的指针变量。

但链表也有缺点(相比较数组)
1.因为地址随机,只能通过遍历来进行查找,查找效率低一些。
2.链表相对于数组来讲,多了指针域空间开销。

按内存存储方式分类,链表可分为静态链表和动态链表。静态链表即为长度固定,可能会造成一定程度上的内存浪费;而动态链表则通过指针实现动态分配内存,可以减少一部分内存的浪费。

按形式分类,链表可分为单向链表、双向链表、循环链表、单向循环列表、双向循环链表。

(图例很清楚故不过多解释)

此外,链表还分为带头与不带头两种。此处的”头“指的是头节点,以下是关于头结点的解释。
(1)数据结构中,在单链表的开始结点之前设立一个节点称之为头节点,头节点的数据域可以不存储任何信息,也可以存储链表的长度等附加信息,头节点的指针域存储指向第一个节点的指针(即第一个节点的存储位置)。
(2)作用:方便链表的操作,减少代码量,举个例子,要知道在链表中插入,删除一个元素是更改这个结点上一个结点的指针域的位置来实现的,那么怎么样来对第一个结点来进行这些操作,有,但是麻烦,不如引入一个头结点来的方便。总之,引入头结点就可以很少的考虑到一些特殊情况,减少代码量。

由于链表通过指针变量串联在一起,所以拿到链表的第一个节点就相当于拿到整个链表。但因为链表不连续,所以寻找某一个节点是一个略显麻烦的事情。

接下来,我们来尝试一步步敲出静态链表。首先,为了实现链表中一个节点包含两个域,我们定义一个结构体。

struct ListNode // 链表节点类型定义
{int data;              // 节点数据struct ListNode* next; // 指向下一个节点的指针
};

[注]:解释一下为什么此处next的类型为ListNode *,因为next的意义是指向下一个节点,而下一个节点的变量类型是我们定义的结构体ListNode,而next又为指针,所以应为ListNode *。

接下来定义一个函数,对每个节点进行初始化(也可以直接在主函数中进行)

void test()
{struct ListNode node1 = {1, NULL};// 定义四个节点struct ListNode node2 = {2, NULL};struct ListNode node3 = {3, NULL};struct ListNode node4 = {4, NULL};node1.next = &node2;// 连接节点node2.next = &node3;node3.next = &node4;//注意最后一个节点的next指针要置为NULLstruct ListNode *pHead = &node1;// 链表头节点
}

Q:此时一个静态链表的最重要的结构已经创建完成了,如果我想要输出这个链表每一个节点存储的数据,应该如何实现呢?

A:通过遍历整个链表实现。

接下来我们实现遍历链表输出数据。如何遍历这个链表呢?因为节点之间通过指针连接,因此我们要访问节点,只能通过指针来实现。
于是我们先定义一个辅助指针变量,例如pCurrent,指向下一个节点。

pCurrent = pCurrent->next;

因为能够指向下一个节点,所以辅助指针变量类型应该是节点的指针,即ListNode*型。
[注]: ->是一个整体,它是用于指向结构体、C++中的class等含有子数据的指针用来取子数据。换种说法,如果我们在C语言中定义了一个结构体,然后申明一个指针指向这个结构体,那么我们要用指针取出结构体中的数据,就要用到“->”
具体可参考这篇CSDN博文C语言结构体--箭头运算符(“->”)和点运算符(“.”) 应用区分_结构体中.和箭头-CSDN博客

Q:遍历自然需要用循环进行实现,那么循环的条件是什么?
A:我们注意到,创建链表的时候,每个节点之间通过next指针连接,而最后一个节点的next指向NULL,因此,当pCurrent更新到最后时应为NULL,此时循环结束。

while (pCurrent != NULL)// 遍历链表{printf("%d ", pCurrent->data);// 输出当前节点数据// 指针移动到下一个元素的位置地址pCurrent = pCurrent->next;}

至此,几个关键的部分都已完成,我们整理一些,补充部分代码。以下为该部分完整的代码

#include <stdio.h>
struct ListNode // 链表节点类型定义
{int data;              // 节点数据struct ListNode *next; // 指向下一个节点的指针
};void test()
{struct ListNode node1 = {1, NULL};// 定义四个节点struct ListNode node2 = {2, NULL};struct ListNode node3 = {3, NULL};struct ListNode node4 = {4, NULL};node1.next = &node2;// 连接节点node2.next = &node3;node3.next = &node4;//注意最后一个节点的next指针要置为NULLstruct ListNode *pHead = &node1;// 链表头指针// 如何遍历链表// 先定义一个辅助指针变量struct ListNode *pCurrent = &pHead;// 辅助指针变量指向头指针while (pCurrent != NULL)// 遍历链表{printf("%d ", pCurrent->data);// 输出当前节点数据// 指针移动到下一个元素的位置地址pCurrent = pCurrent->next;}
}
int main()
{test();// 调用test函数return 0; // 程序结束
}

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

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

相关文章

VGGNet模型的训练和推理

VGGNet 2024年5月10日更新 在此教程中,我们将对VGGNet模型及其原理进行一个简单的介绍,并实VGGNet模型的训练和推理,目前支持数据集有:MNIST、fashionMNIST、CIFAR10等,并给用户提供一个详细的帮助文档。 目录 基本介绍VGGNett描述 创新点 网络结构 VGGNet的特点VGGNet实现…

ResNet模型的训练和推理

ResNet 2024年5月7日更新 在此教程中,我们将对ResNet模型及其原理进行一个简单的介绍,并实现ResNet模型的训练和推理,目前支持数据集有:MNIST、fashionMNIST、CIFAR10等,并给用户提供一个详细的帮助文档。 目录 基本介绍ResNet描述 为什么要引入ResNet? 网络结构分析ResN…

转载:【AI系统】AI编译器前瞻

本文首先会基于 The Deep Learning Compiler: A Comprehensive Survey 中的调研做一个热门 AI 编译器的横向对比,并简要介绍几个当前常用的 AI 编译器。随后会分析当前 AI 编译器面临的诸多挑战,并展望 AI 编译器的未来。 业界主流 AI 编译器对比 在 The Deep Learning Compi…

Docker部署Mikochi,轻松管理文件上传下载

1.基本条件 (1)准备一台服务器 (2)部署docker、docker-compos服务 (3)创建数据储存目录mkdir -p /data/mikochi/data 2.部署mikochi[root@localhost mikochi]# cat docker-compose.yaml version: 3.7services:mikochi:image: zer0tonin/mikochi:1.7.0container_name: m…

[QT] MAC使用Qt Creator运行程序如何仅运行一个进程?

问题背景刚开始在 Mac 使用 QT Creator 运行项目时会发现每次 Run 程序都出现一个新的任务进程,而非类似 Windows 环境下是先 stop 之前的进程再创建。那么如何每次run后,就关闭上一次的进程,而重新拉起新进程呢? 解决方案

Windows 配置自动更新重启策略

I. 打开策略编辑器 【Win + R】打开 “运行” 窗口,输入: gpedit.msc打开“本地组策略编辑器”。 II. 设置不自动重启 启用策略,选择在你任何想要重启的时候重启计算机。III. 重启计算机 重启计算机,完成配置。

笔记本电脑蓝屏 硬盘损坏数据恢复

当笔记本电脑出现蓝屏故障,并且怀疑硬盘已损坏需要恢复数据时,可以参考以下步骤和建议: 一、初步处理 断开电源:在尝试任何数据恢复操作之前,首先要断开笔记本电脑的电源,以避免进一步的数据损坏或丢失。 评估蓝屏原因:蓝屏可能是由驱动程序错误、系统文件损坏、硬件故障…

.NET Core 堆结构(Heap)底层原理浅谈

https://www.cnblogs.com/lmy5215006/p/18583743 .Net托管堆布局加载堆 主要是供CLR内部使用,作为承载程序的元数据。HighFrequencyHeap存放CLR高频使用的内部数据,比如MethodTable,MethodDesc.通过is判断类型之间的继承关系,调用接口的方法和虚方法,都需要访问MethodTable…

简化版 先求每个商品品类中亏损的最大的 写入新的表中

import pandas as pd # 读取原始表 简化为仅求亏损最大的 # 路径需要双斜杠 data = pd.read_excel(D:\\work\\2\\配料统计表.xlsx,sheet_name=Sheet1) # 对数据做处理 #第一步 找到亏损类和涨出类 如果金额大于0 是亏损;否则是涨出 data_loss= data[data[差异金额]>0] …

ABB IRB4400机器人示教器维修黑屏问题

当ABB机器人IRB4400的示教器出现黑屏问题时,可能的原因包括硬件故障、软件冲突或外部干扰。以下是一些可能的解决方法:硬件故障检查:检查示教器显示屏是否损坏或老化。检查与显示屏连接的电缆或电路板是否出现故障。更换损坏的部件。软件冲突检查:检查示教器的操作系统或应…

使用正点原子的直流无刷驱动板自写FOC控制永磁同步(PMSM)电机(开环位置)

由于ST官方MotorControlWorkbench生成的FOC代码过于复杂,决定自己使用正点原子的直流无刷驱动板自己编写FOC去控制PMSM电机。FOC代码参考的是灯哥的教材DengFOC官方文档。 1、配置TIM1高级定时器 2、foc.c代码/** foc.c** Created on: Dec 11, 2024* Author: ME-LZQ*/#i…