C语言:创建带头结点的动态链表:解析与实现

embedded/2025/2/4 6:37:20/

创建带头结点的动态链表:解析与实现

在本博客中,我们将逐步解析一个C语言程序,该程序用于创建一个带头结点的动态链表。链表用于存储从键盘输入的学生高考总分,以任意负数作为输入结束标志。最终,程序返回链表的头指针,并在主函数中调用该功能。

代码目标

  • 创建一个带头结点的动态链表。

  • 从键盘输入一批学生的高考总分(以负数作为结束标志)。

  • 返回链表的头指针。

  • 在主函数中调用该功能并打印头指针。

代码实现

数据结构定义

struct node 
{int data;           // 存储学生高考总分struct node * next; // 指向下一个节点的指针
};
typedef struct node NODE; // 为struct node定义别名NODE
  • 定义了一个结构体node,用于表示链表的节点。

  • 每个节点包含两个成员:

    • data:存储学生高考总分。

    • next:指向下一个节点的指针。

  • 使用typedefstruct node定义了别名NODE,方便后续代码中使用。

创建链表的函数

NODE *create()
{NODE *head, *p, *q; // 末节点指针p,新节点指针qint t;head = malloc(sizeof(NODE)); // 分配头结点内存p = head;                   // 初始化p为头结点while (1){printf("输入整数(负数为结束):");scanf("%d", &t); // 从键盘输入一个整数if (t < 0)break; // 如果输入为负数,结束输入q = malloc(sizeof(NODE)); // 分配新节点内存q->data = t;              // 将输入的整数存储到新节点的数据域p->next = q;              // 将新节点链接到链表末尾p = q;                    // 将p移动到新节点}p->next = NULL; // 将链表末尾的next指针设置为NULLreturn head;    // 返回头指针
}
  • 头结点初始化

    • 使用malloc为头结点分配内存。

    • p初始化为头结点,p用于跟踪链表的末尾。

  • 循环输入数据

    • 使用while (1)循环不断从键盘输入数据。

    • 如果输入的数为负数,使用break退出循环。

    • 否则,为新节点分配内存,存储输入的数据,并将新节点链接到链表末尾。

  • 链表结束

    • 将链表末尾节点的next指针设置为NULL,表示链表结束。

  • 返回头指针

    • 返回头结点的指针head,作为链表的入口。

主函数

c复制

int main(void)
{NODE *h;h = create(); // 调用create函数创建链表printf("头指针%p\n", h); // 打印链表的头指针return 0;
}
  • 在主函数中调用create函数,创建链表并获取头指针。

  • 打印链表的头指针地址。

代码问题与修正

虽然代码实现了基本功能,但存在一些问题和潜在的改进点:

问题1:错误的链表链接

c复制

p->next = q->next;
  • 这行代码是错误的,应该改为:

c复制

p->next = q;
  • 原因q->next在新节点q分配内存后未初始化,直接赋值会导致未定义行为。

修正后的代码

NODE *create()
{NODE *head, *p, *q; // 末节点指针p,新节点指针qint t;head = malloc(sizeof(NODE)); // 分配头结点内存p = head;                   // 初始化p为头结点while (1){printf("输入整数(负数为结束):");scanf("%d", &t); // 从键盘输入一个整数if (t < 0)break; // 如果输入为负数,结束输入q = malloc(sizeof(NODE)); // 分配新节点内存q->data = t;              // 将输入的整数存储到新节点的数据域p->next = q;              // 将新节点链接到链表末尾p = q;                    // 将p移动到新节点}p->next = NULL; // 将链表末尾的next指针设置为NULLreturn head;    // 返回头指针
}

问题2:未释放内存

  • 在实际应用中,链表使用完毕后应释放分配的内存,避免内存泄漏。

  • 可以在主函数中添加链表的遍历和释放操作。

完整的改进代码

#include <stdio.h>
#include <stdlib.h>struct node 
{int data;struct node * next;
};
typedef struct node NODE;NODE *create()
{NODE *head, *p, *q; // 末节点指针p,新节点指针qint t;head = malloc(sizeof(NODE)); // 分配头结点内存p = head;                   // 初始化p为头结点while (1){printf("输入整数(负数为结束):");scanf("%d", &t); // 从键盘输入一个整数if (t < 0)break; // 如果输入为负数,结束输入q = malloc(sizeof(NODE)); // 分配新节点内存q->data = t;              // 将输入的整数存储到新节点的数据域p->next = q;              // 将新节点链接到链表末尾p = q;                    // 将p移动到新节点}p->next = NULL; // 将链表末尾的next指针设置为NULLreturn head;    // 返回头指针
}void free_list(NODE *head)
{NODE *current = head;NODE *temp;while (current != NULL){temp = current;current = current->next;free(temp);}
}int main(void)
{NODE *h;h = create(); // 调用create函数创建链表printf("头指针%p\n", h); // 打印链表的头指针// 释放链表内存free_list(h);return 0;
}

总结

通过本博客,我们详细解析了一个用于创建带头结点动态链表的C语言程序。我们修正了代码中的错误,并添加了内存释放功能,以避免内存泄漏。希望这篇博客能帮助你更好地理解链表的创建和管理,以及如何在实际应用中避免常见的错误。

如果你有任何问题或建议,欢迎在评论区留言!


http://www.ppmy.cn/embedded/159393.html

相关文章

基于YOLO11的遥感影像山体滑坡检测系统

基于YOLO11的遥感影像山体滑坡检测系统 (价格90) 按照7&#xff1a;2&#xff1a;1随机划分&#xff1a;训练集 6736张 验证集 1924张 测试集 963张 包含 [slide] [山体滑坡] 1种情况 通过PYQT5构建UI界面&#xff0c;包含图片检测&#xff0c;视频检测&…

SpringBoot+Electron教务管理系统 附带详细运行指导视频

文章目录 一、项目演示二、项目介绍三、运行截图四、主要代码1.查询课程表代码2.保存学生信息代码3.用户登录代码 一、项目演示 项目演示地址&#xff1a; 视频地址 二、项目介绍 项目描述&#xff1a;这是一个基于SpringBootElectron框架开发的教务管理系统。首先&#xff…

深入学习华为IPD流程之华为-PDT经理角色认知培训教材

本文介绍了PDT经理的角色认知,包括其在IPD体系中的位置、基本角色定位、关键管理活动、能力模型和评估方法以及培养路径。文章指出PDT经理是重量级产品开发团队的管理者,负责产品的商业成功和跨功能部门合作,通过绩效管理加强团队凝聚力,对商业结果负责。 重点内容: 1. …

机器人抓取与操作概述(深蓝)——1

工业机器人&#xff1a;① “臂”的形态 ② “手”的形态 ③ 视觉&#xff0c;力和触觉 1 机器人的不同形态 “臂”的形态 “手”的形态 2 常见的操作任务 操作&#xff1a;插入、推和滑 抓取&#xff1a;两指&#xff08;平行夹爪&#xff09;抓取、灵巧手抓取 落地-产…

51单片机开发:独立键盘实验

实验目的&#xff1a;按下键盘1时&#xff0c;点亮LED灯1。 键盘原理图如下图所示&#xff0c;可见&#xff0c;由于接GND&#xff0c;当键盘按下时&#xff0c;P3相应的端口为低电平。 键盘按下时会出现抖动&#xff0c;时间通常为5-10ms&#xff0c;代码中通过延时函数delay…

gdb 调试多进程中多线程的方法

示例代码 首先&#xff0c;给出一个简单的示例程序&#xff0c;演示如何使用 fork 创建多个子进程并且每个进程内部创建多个线程。 示例代码 (main.cpp) #include <iostream> #include <thread> #include <vector> #include <unistd.h> #include <…

《大语言模型》综述学习笔记

《A Survey of Large Language Models》英文版综述最近出了中文版书——《大语言模型》&#xff0c;本博客作为阅读笔记记录一下&#xff0c;综述主页&#xff1a;https://github.com/RUCAIBox/LLMSurvey 关于LLM的一些概述和理解 记录一些有启发性的说法&#xff1a; 1、当前…

SpringBoot使用 easy-captcha 实现验证码登录功能

文章目录 一、 环境准备1. 解决思路2. 接口文档3. redis下载 二、后端实现1. 引入依赖2. 添加配置3. 后端代码实现4. 前端代码实现 在前后端分离的项目中&#xff0c;登录功能是必不可少的。为了提高安全性&#xff0c;通常会加入验证码验证。 easy-captcha 是一个简单易用的验…