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

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

时间:2024-12-12 13:31:57浏览次数:3  
标签:ListNode struct 一步步 更新 next 链表 节点 指针

链表的一步步实现(需有一部分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指针要置为NULL
    
    struct 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指针要置为NULL

    struct ListNode *pHead = &node1;// 链表头指针

    // 如何遍历链表

    // 先定义一个辅助指针变量
    struct ListNode *pCurrent = &pHead;// 辅助指针变量指向头指针
    while (pCurrent != NULL)// 遍历链表
    {
        printf("%d ", pCurrent->data);// 输出当前节点数据
        // 指针移动到下一个元素的位置地址
        pCurrent = pCurrent->next;
    }
}
int main()
{
    test();// 调用test函数
    return 0; // 程序结束
}

标签:ListNode,struct,一步步,更新,next,链表,节点,指针
From: https://www.cnblogs.com/WisdomWu/p/18599036

相关文章

  • 在 PowerShell 中实现您要求的多个网络修复功能,可以通过运行多个脚本和命令来完成。这
    ResetInternetProtocols(TCP/IP)RepairWinsock(ResetCatalog)RenewInternetConnectionsFlushDNSResolverCache(DomainNameSystem)FlushARPCache(AddressResolutionProtocol)RepairInternetExplorer11ClearWindowsUpdateHistoryRepairWindows/Automat......
  • php网站前端页面修改,如何更新PHP网站前端页面
    更新PHP网站的前端页面是提升用户体验和优化设计的重要步骤。以下是详细的修改步骤:确定需要修改的页面:列出需要更新的页面,如首页、产品页、关于我们页等。备份文件:在进行任何修改之前,请确保备份网站的所有文件和数据库,以防出现问题时能够恢复。编辑HTML文件:找到......
  • macOS Sequoia 15.2 发布下载,带来 Apple 智能重大更新
    macOSSequoia15.2(24C101)正式版ISO、IPSW、PKG下载iPhone镜像、Safari浏览器重大更新和AppleIntelligence等众多全新功能令Mac使用体验再升级请访问原文链接:https://sysin.org/blog/macOS-Sequoia/查看最新版。原创作品,转载请保留出处。作者主页:sysin.orgmacO......
  • 解决因注册表缺失导致的 Edge 无法启动、安装、更新
    解决因注册表缺失导致的Edge无法启动、安装、更新学校的电脑装的GhostWindows10应该是把Edge相关的注册表给精简了,导致了Edge浏览器无法更新,也无法启动安装程序。解决方法对症下药,添加注册表即可。首先新建一个文本文件,在里面添加如下内容:WindowsRegistryEditor......
  • 数据结构与算法之美:再谈单链表(进阶)
            Hello大家好!很高兴我们又见面啦!给生活添点passion,开始今天的编程之路!我的博客:<但凡.我的专栏:《数据结构与算法之美》、《编程之路》、《题海拾贝》欢迎点赞,关注! 目录 1、使用C++实现单链表1.1节点的声明1.2节点的初始化1.3头插和尾插1.3.1头插......
  • 2023 ICPC 合肥区域赛题解 更新至 6 题(The 2023 ICPC Asia Hefei Regional Contest )
    Preface只能说阅读理解能力有待提高,\(B\)题看了半天愣是看不懂一点。只能跳了。依旧是复习篇,感觉队友当时开出来的\(dp\)难度不低,感慨张神的强大。我会在代码一些有必要的地方加上注释,签到题可能一般就不会写了.以下是代码火车头:#include<iostream>#include<algorithm>#i......
  • 链表(头插法)
    利用头插法,创建类似下图所示的动态链表,其中结点数据域由键盘输入而确定。要创建下图的链表,输入的依次是DCBA。创建好链表后,还需要依次访问各个结点,输出各个结点的数据域。输入 1行,4个字符输出4个字符,次序与输入相反,中间用空格分隔。样例输入XYUW样例输出WUYX#inc......
  • 合并两个有序链表
    力扣链接:21.合并两个有序链表-力扣(LeetCode)将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。示例1:输入:l1=[1,2,4],l2=[1,3,4]输出:[1,1,2,3,4,4]示例2:输入:l1=[],l2=[]输出:[]示例3:输入:l1=......
  • 电脑无法开机?从有经验的技术员角度来一步步教你解决
    电脑是现代生活中不可或缺的生产力工具,无论是消费者使用的台式机电脑还是个人笔记本电脑,亦或是工业应用的工控机,如果一旦出现故障,将会给我们的工作和生活上带来极大的不便,尤其是工控机作为工业设备中的核心控制电脑,若是在工厂自动化应用中的工控机发生故障的话,可能会造成生产线的......
  • 反转链表 II
    题解:/***Definitionforsingly-linkedlist.*structListNode{*intval;*structListNode*next;*};*/structListNode*reverseBetween(structListNode*head,intleft,intright){structListNode*dummy=(structListNode*)malloc(s......