news 2026/10/26 1:52:19

程序设计题|建立3结点学生链表,输出第一个学生信息

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
程序设计题|建立3结点学生链表,输出第一个学生信息

程序设计题|建立3结点学生链表,输出第一个学生信息

题目:编程建立一个三个结点的链表,存放三个学生的数据,并输出第一个学生的数据信息。假定学生数据结构中只有学号、姓名、成绩三项。可编写一个建立链表的函数creat()。(可自行定义结构体类型)

完整C代码(可直接编译运行)

#include<stdio.h>#include<stdlib.h>#include<string.h>// 定义学生链表节点typedefstructStudent{intid;// 学号charname[20];// 姓名floatscore;// 成绩structStudent*next;}StuNode;// 创建3个节点链表,返回链表头指针StuNode*creat(){StuNode*p1,*p2,*p3;// 开辟3个节点内存p1=(StuNode*)malloc(sizeof(StuNode));p2=(StuNode*)malloc(sizeof(StuNode));p3=(StuNode*)malloc(sizeof(StuNode));// 学生1赋值p1->id=1001;strcpy(p1->name,"Zhang");p1->score=92.5;// 学生2赋值p2->id=1002;strcpy(p2->name,"Li");p2->score=88.0;// 学生3赋值p3->id=1003;strcpy(p3->name,"Wang");p3->score=79.3;// 串联节点p1->next=p2;p2->next=p3;p3->next=NULL;returnp1;// 返回第一个节点地址}intmain(void){StuNode*head;head=creat();// 输出第一个学生信息printf("=====第一个学生信息=====\n");printf("学号:%d\n",head->id);printf("姓名:%s\n",head->name);printf("成绩:%.1f\n",head->score);// 释放内存(从head出发,逐个节点释放)StuNode*p=head,*q;while(p!=NULL){q=p;// 记录当前节点地址p=p->next;// 先移到下一个节点free(q);// 再释放当前节点}return0;}

运行输出:

=====第一个学生信息===== 学号:1001 姓名:Zhang 成绩:92.5

逐行小白解析

1. 结构体定义

typedefstructStudent{intid;// 学号charname[20];// 姓名,字符数组保存字符串floatscore;// 成绩structStudent*next;// 指针,存下一个节点地址}StuNode;
  • typedef:给struct Student起别名StuNode,简化后续代码。
  • 每个节点 = 学生数据 +next指针,用来链接下一个学生。

2. creat() 创建链表函数

StuNode*creat()
  • 返回值StuNode*:返回节点的内存地址(链表起点)。
StuNode*p1,*p2,*p3;p1=(StuNode*)malloc(sizeof(StuNode));
  • p1,p2,p3:指针变量(相当于纸条,只存地址,本身不是节点)
  • malloc:在堆内存开辟一块空间,生成真正的学生节点。
strcpy(p1->name,"Zhang");

重点:字符数组不能直接用=赋值字符串,要用strcpy,需要头文件<string.h>。

p1->next=p2;p2->next=p3;p3->next=NULL;

链表串联:p1 → p2 → p3 → NULL
NULL标记链表末尾,代表后面没有节点。

returnp1;

把第一个学生节点的地址返回给main函数。

3. main主函数

StuNode*head;head=creat();

调用creat()创建链表,head保存链表第一个节点地址。

printf("学号:%d\n",head->id);printf("姓名:%s\n",head->name);printf("成绩:%.1f\n",head->score);

head直接指向第一个学生节点,用->读取数据打印。

✅ 重点详解:链表内存释放(为什么 free(q) 能释放 p 的节点)

第一步:理解 p 和 q 到底是什么

先把内存分成两部分想清楚:

渲染错误:Mermaid 渲染失败: Lexical error on line 2. Unrecognized text. ...t LR subgraph 栈区【两张小纸条】 p["p ----------------------^

关键点:

  1. 节点本身在堆区(malloc开出来的),它是一间"房间",里面住着 1001、Zhang、92.5 这些数据。
  2. p 和 q 在栈区,它们不是节点,只是两张"小纸条",纸条上写的是房间号(内存地址)。
  3. q = p;这句话,不是把整个节点复制一份给 q,只是把 p 纸条上的房间号抄写到 q 纸条上。
    • 结果:p 纸条 = 房间号0x100,q 纸条 = 房间号0x100,两张纸条指向同一间房间。

第二步:free 到底做了什么

free(q);
  • free不是"清空 q 这个变量"!
  • free是:看括号里那个地址(房间号),去堆区把那个房间整个拆掉。
  • free(q)=free(0x100),就是把 0x100 这间房间拆掉。
  • q 纸条本身还在,还在栈区,只是它指向的房间没了。

打个比方:q 是一张写着"幸福小区3栋101"的纸条,
free(q)是照着这个门牌号去把101房间拆掉,不是撕掉纸条本身。

第三步:为什么释放前要先移动 p

q=p;// q 先记住当前房间号p=p->next;// p 先跑到下一个房间(提前拿到下一个房间号)free(q);// 现在才拆当前房间

如果不先移动 p,直接 free:

// ❌ 错误写法while(p!=NULL){free(p);// 当前房间被拆掉了p=p->next;// 还想去已拆掉的房间里拿 next 地址 → 崩溃!}

房间都没了,里面的 next 纸条也一起没了,p 再也拿不到下一个房间号,程序就崩了。
所以顺序必须是:先记下下一个房间号(移动p),再拆当前房间(free(q))。

第四步:三轮循环完整模拟(对照代码看)

链表:p1(地址0x100) → p2(地址0x200) → p3(地址0x300) → NULL

第3轮

第2轮

第1轮

p=0x100
q=p → q=0x100
p=p->next → p=0x200
free(0x100) 拆p1

p=0x200
q=p → q=0x200
p=p->next → p=0x300
free(0x200) 拆p2

p=0x300
q=p → q=0x300
p=p->next → p=NULL
free(0x300) 拆p3

  • 第1轮:p 在 p1,q 记住 p1 地址;p 先跑到 p2;free 按 q 上的地址拆掉 p1。
  • 第2轮:p 在 p2,q 记住 p2 地址;p 先跑到 p3;free 按 q 上的地址拆掉 p2。
  • 第3轮:p 在 p3,q 记住 p3 地址;p 先跑到 NULL;free 按 q 上的地址拆掉 p3。
  • 第4轮:p == NULL,循环结束,三个节点全部释放。

第五步:为什么 main 里不能直接 free(p1)

StuNode*creat(){StuNode*p1,*p2,*p3;// 这三个变量是 creat 的局部变量...returnp1;}
  • p1/p2/p3 是 creat 函数内部的局部变量,函数一结束就"消失"了。
  • main 里根本认不到 p1/p2/p3 这个名字,写了 free(p1) 会编译报错。
  • 但节点本身是 malloc 在堆区开的,没有消失,只能靠 head 顺着链表一个个找到并释放。

Mermaid内存图(可直接放进Obsidian)

堆区 三个学生节点

栈区

虚线

实线next

实线next

head

id:1001
name:Zhang
score:92.5
next → N2地址

id:1002
name:Li
score:88.0
next → N3地址

id:1003
name:Wang
score:79.3
next = NULL

小白易错点

  1. 忘记头文件:<stdlib.h>用于malloc,<string.h>用于strcpy
  2. 不能写p1->name="Zhang",字符数组禁止直接字符串赋值
  3. 尾节点一定要写next=NULL,否则链表没有结束标记
  4. 指针不等于节点:StuNode *p只是地址纸条,malloc之后才有真实节点
  5. p1/p2/p3是creat里的局部变量,main里不能直接用,释放内存要从head出发遍历
  6. 释放链表节点必须先保存下一个节点地址(移动p),再free,顺序颠倒会造成程序崩溃
  7. free 释放的是堆内存里的节点(按地址拆房间),不是删除 p/q 这两个指针变量,指针变量还在栈区
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/26 1:52:19

HarmonyOS 7.0学习笔记58:AI能力接入前的接口与隐私边界

&#x1f525; 个人主页&#xff1a;杨利杰YJlio ❄️ 个人专栏&#xff1a;《Windows 疑难杂症与工单复盘案例库》 《Sysinternals实战教程》 《WINDOWS教程》 《Windows PowerShell 实战》 《IOS插件分析测试》 《超简单&#xff1a;用Python让Excel飞起来》 &am…

作者头像 李华
网站建设 2026/10/26 1:50:11

GTweak Windows 优化反馈渠道怎么选:一条路都不走错的避坑地图

GTweak Windows 优化反馈渠道怎么选&#xff1a;一条路都不走错的避坑地图 【免费下载链接】GTweak Portable Tool for an Ideal Windows Setup 项目地址: https://gitcode.com/GitHub_Trending/gt/GTweak GTweak 是一款免安装、单文件的工具&#xff0c;把 Windows 10/…

作者头像 李华
网站建设 2026/10/26 1:50:11

MiniMax H3本地部署要多少显存?一张科室清单讲透下载、选型与2K真相

MiniMax H3本地部署要多少显存&#xff1f;一张科室清单讲透下载、选型与2K真相 【免费下载链接】MiniMax-H3 MiniMax H3 是一个通用的全模态生成系统。它支持对由文本、图像、视频和音频组成的多模态上下文进行统一理解&#xff0c;并能生成分辨率高达 2K、时长可达 15 秒的带…

作者头像 李华