再探C语言链表—TypeDef Struct模式声明链表节点

2023-05-16

0. 序

之前看到的网上的书上的都是Struct直接创建节点。

我记得typedef struct是大学时候数据结构课本上用来声明链表结点的方法,这个方法让人容易操作链表。后来书本扔了,再买了盗版书不知道是版本问题还是什么问题,包括网上大多数博客都是直接struct声明。struct直接声明对后面链表的增删改查都稍微增加了难度。

今天在查资料时候突然看到这个写法,操作了一遍发现很容易实现链表的一些基本操作,因此完善一下贴上来

1. 代码

代码比较简单,重要的地方注释了

#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>

typedef struct List
{
    int val;
    struct List *next;
} link;

/*------------------------------初始化节点--------------------------------*/
link *InitNode()
{
    printf("开始初始化结点\n");
    link *head = (link *)malloc(sizeof(link)); //初始化头结点
    head->next = NULL;                         //初始化时候头结点的下一个结点一定要指向空,否则会指向随机地址
    printf("初始化结点已完成\n");
    return head;
}

/*------------------------------遍历节点--------------------------------*/
void PrintNode(link *head)
{
    while (head->next != NULL)
    {
        head = head->next; //因为有头结点,但是头结点没有存数据,所以从头结点的下一个结点开始遍历
        printf("%d\n", head->val);
    }
}

/*------------------------------尾插法添加节点--------------------------------*/
void AppendNodeR(link *head, int t)
{
    link *a = (link *)malloc(sizeof(link));
    a->val = t;
    a->next = NULL;
    printf("开始尾插法添加结点 %d\n", t);
    while (head->next != NULL)
    {
        head = head->next;
    }
    head->next = a;
    printf("尾插法添加结点已完成\n");
}

/*------------------------------头插法添加节点--------------------------------*/
void AppendNodeL(link *head, int t)
{
    link *a = (link *)malloc(sizeof(link));
    a->val = t;
    a->next = NULL;
    printf("开始头插法添加结点 %d\n", t);
    a->next = head->next;
    head->next = a;
    printf("头插法添加结点已完成\n");
}

/*------------------------------删除节点--------------------------------*/
void DeleteNode(link *head, int t)
{
    link *temp = (link *)malloc(sizeof(link)); //初始化头结点
    link *d = head;
    printf("开始删除目标结点: %d\n", t);
    while (d->next != NULL)
    {
        temp = d;
        d = d->next; //因为有头结点,但是头结点没有存数据,所以从头结点的下一个结点开始遍历
        if (d->val == t)
        {
            temp->next = d->next; //d在这里已经后移一位
            printf("已删除结点: %d\n", d->val);
        }
    }
}

int main()
{
    link *head = InitNode(); //因为这个头结点在后面都用上了,所以需要返回一个头结点

    AppendNodeR(head, 0); //因为我们是以指针也就是地址的方式传过去,所以不需要重新返回链表
    AppendNodeR(head, 1);
    AppendNodeR(head, 2);
    AppendNodeR(head, 3);
    AppendNodeR(head, 4);
    AppendNodeR(head, 5);
    AppendNodeR(head, 6);
    AppendNodeR(head, 7);
    AppendNodeR(head, 8);
    AppendNodeR(head, 9);
    AppendNodeR(head, 10);
    PrintNode(head);

    DeleteNode(head, 3);
    PrintNode(head);

    AppendNodeL(head, 20);
    AppendNodeL(head, 21);
    AppendNodeL(head, 22);
    PrintNode(head);

    system("pause"); //shell暂停函数,不加的话黑框一闪而过。调用system需要加stdlib头文件
}

 结果

2. 头插法示意图

因为头插法稍微拐了个弯,我之前也没搞明白,画个图就明白了

 链表的头节点是指向下一个节点,因此在插入新节点时候,首先是把待插入节点指向头结点的下一个节点,然后再把头结点地址指向待插入节点。

如下,a是待插入节点,head是head的下一个节点。

    a->next = head->next;
    head->next = a;

 3. 关于我代码里面的很多head

可能我这里很多都是head,但是这个是传入的head的地址,因此虽然看着他们重新声明了好多次,但是在main函数里面传入的是同一个head,因此这里的head实际上地址都是一样的。

后面我再讲一下遍历里面的head可能会更清楚点

 4. 关于遍历函数里面的head

我这里算是故意写了head,如果你能把这个head弄懂,就说明真的弄懂链表了

我们这里的head=head.next就是移动指针。

又因为这里的head实际上是一个新的局部地址(指针)变量,所以我们改变这里的值,对main函数里面的head是没有影响的。

5. 关于链表的地址

 实际上我们在用malloc申请内存时候,就已经在内存里面开辟了一块地址。

是保存在堆里面还是在栈里面,我们下次再讨论。

如图我们看到三个地址,这就是head、p、t所在的位置。

 当我们把next给指向(赋值,让next等于指向的节点的地址)所在节点的地址后,地址就变成指向节点的地址,新手往往在指向地址的时候懵了,不知道是谁指谁。

这里明确说明,是next=想要指向的节点的地址

如下图就是让next指向下一个节点的示意图

 如下图就是在指向节点之后各个地址值

 6. 关于next指向NULL

这张图里面我们可以看到,在我们使用malloc创建了一个结构体指针变量之后,他的值是一个明确的地址。而我们的结构体里面的结构体指针因为没有使用malloc,所以他指向的是一个随机值,如下图在指向地址之前是一个相同的值,他们都指向了同一个地方。

因此在初始化和添加节点的时候next指向NULL是非常重要的,如果没有指到NULL,我们在遍历的时候就找不到尾结点在什么地方。对了,这里说明一下,我们判断尾结点的方式就是判断当前结点的next是不是指向NULL,如果指向NULL就说明他是尾结点。

 因此一定要注意新建的节点的next一定要指向NULL

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

再探C语言链表—TypeDef Struct模式声明链表节点 的相关文章

随机推荐

  • 使用snprintf函数使用时注意事项

    snprintf函数 函数原型 xff1a int snprintf char str size t size const char format 简介 xff1a 将可变参数 按照format的格式格式化为字符串 xff0c 然后再将其拷
  • UCOSii中的信号量

    任务间简单通个信 xff0c A告诉B你LED亮一下 这种问题可以用信号量来处理 xff0c UCOSii中关于信号量的函数也就八个 xff0c 今天简单总结下 函数列表 CREATE A SEMAPHORE Description Thi
  • FreeRTOS中的变量,函数命名规则(u.v.x.p什么意思)

    写在前面 初学FreeRTOS时 xff0c 每次打开函数列表都一脸懵逼 xff1f 根本不知道这什么prv v ux是什么意思 xff0c 虽然平时使用也不需要知道这么多东西 xff0c 因为它不怎么影响开发 xff0c 但是理解总比疑惑
  • stm32学习之路---最小系统的介绍

    目标 xff1a stm32最小系统的了解 1 STM32最小系统组成 电源电路复位电路晶振电路下载电路 电源电路 xff1a DC IN1和POWER那是单片机的火牛接口它是5V的 xff0c 不能乱接不然会烧毁芯片 POWER1处是单片
  • 视频目标检测(video object detection)简单综述

    对目前看过的视频目标检测论文做一个简单的综述 xff0c 也欢迎大家补充一些其他遗漏掉的 xff0c 不错的视频目标检测论文 持续更新 github https github com breezelj video object detect
  • AAAI2021第一轮被拒经验分享

    AAAI第一轮悲剧了 俩5分 俩评委给的意见都挺中肯的 xff0c 主要还是创新性不过 xff0c 加基线算法比较不够 对实验结果解释不足 感觉他们对实验方法细节并没有很着重看 xff0c 更多的是宏观的评论 第一次投多少有点失望 xff0
  • C语言Sprintf用法

    如图 xff0c 两种简单用法 include lt iostream gt include lt stdio h gt 程序的主函数 int main char a 20 a 0 61 39 p 39 a 1 61 39 t 39 spr
  • UE4——打印函数

    输出当前类名 xff0c 注意是两个 GEngine gt AddOnScreenDebugMessage 0 30 f FColor Red FString FUNCTION 输出当前物体名 GEngine gt AddOnScreenD
  • vscode主题

    刚发现的 xff0c 代码效果比较好
  • VSCode 全局搜索正则排除不想显示的文件

    排除前 排除后 lst
  • 串口打印小数

    一般串口是打印一个8位字符 xff0c 或者打印一个数组 xff0c 如果要打印小数 xff0c 就要用到格式化输出 xff0c 把小数格式化输出到数组里面 u8 a 10 b 10 co2 61 1 001 tvoc 61 2 001 s
  • UE4——蓝图多重for循环

    1 示例 如下打印 xff0c 说明成功进行3次循环
  • C++链表

    上个简单链表 xff0c 写的有些难看 xff0c 现在更改一下 https liu endong blog csdn net article details 111934018 添加了删除尾结点 xff0c 添加了删除头结点 includ
  • 电路设计——发光二极管限流电阻

    0 序 最近在设计电路画板子了 xff0c 画完发现 xff0c 这电阻电容咋用啊我去 于是来学一下电阻和电容的使用 1 限流电阻作用 限流电阻主要是为了防止电流过大损坏器件 这里的限流其实还起到分压的作用 xff0c 比如我们单片机出来的
  • stm32cubeMX+FreeRTOS(4)—— main函数while循环

    0 发现 想在主函数中打印一下串口数据 xff0c 发现一直打印不出来 xff0c 试了下开关小灯 xff0c 发现没有进main函数的while循环 xff0c 阿西吧 xff0c 我大概要重新看一下CubeMX的rtos架构了 本来打算
  • Docker常见操作

    记录docker使用过程中的常用操作 1 xff0c 拉取镜像 docker pull image name image tag such as ubuntu 18 04 2 xff0c 列出所有镜像和容器 docker images do
  • stm32cubeMX+FreeRTOS(5)—— 串口打印

    0 序 cubeMX的FreeRtos和hal库的打印方式一样 本文基于CubeMX6 1 1版本编写 xff0c 此时CubeMX6 3 1已经无法使用此代码 xff08 2022 1 17 xff09 1 CubeMX配置串口 点一下串
  • HLK-B36 WIFI/BLE 二合一透传沙雕按键说明

    模块如下 沙雕说明如下 实际操作如下 恢复出厂设置 xff1a 插usb上电 xff0c 长按ES0 6秒以上 xff0c WIFI灯和STA灯同时灭掉然后亮起 xff0c STA开始闪烁 进入AT模式方式1 xff1a 插上USB xff
  • VScode下载安装及使用教程

    0 序 1 下载 官网下载速度特别慢 xff0c 需要用国内镜像 官网 xff1a Visual Studio Code Code Editing Redefined国内 点进去之后会过慢慢打开下载链接 xff0c 速度非常慢 跳转到这个界
  • 再探C语言链表—TypeDef Struct模式声明链表节点

    0 序 之前看到的网上的书上的都是Struct直接创建节点 我记得typedef struct是大学时候数据结构课本上用来声明链表结点的方法 xff0c 这个方法让人容易操作链表 后来书本扔了 xff0c 再买了盗版书不知道是版本问题还是什