题目要求
本题要求实现一个将输入的学生成绩组织成单向链表的简单函数。
函数接口定义:
void input();
该函数利用scanf从输入中获取学生的信息,并将其组织成单向链表。链表节点结构定义如下:
struct stud_node {
int num; /*学号*/
char name[20]; /*姓名*/
int score; /*成绩*/
struct stud_node *next; /*指向下个结点的指针*/
};
单向链表的头尾指针保存在全局变量head和tail中。
输入为若干个学生的信息(学号、姓名、成绩),当输入学号为0时结束。
裁判测试程序样例:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct stud_node {
int num;
char name[20];
int score;
struct stud_node *next;
};
struct stud_node *head, *tail;
void input();
int main()
{
struct stud_node *p;
head = tail = NULL;
input();
for ( p = head; p != NULL; p = p->next )
printf("%d %s %d\n", p->num, p->name, p->score);
return 0;
}
/* 你的代码将被嵌在这里 */
输入样例:
1 zhang 78
2 wang 80
3 li 75
4 zhao 85
0
输出样例:
1 zhang 78
2 wang 80
3 li 75
4 zhao 85
解题思路
结合所给代码,可分析代码功能实现如下:
使用结构体定义学生信息节点,包括学号、姓名、分数以及指向下一个节点的指针成员变量。
函数 void input()
用于读取用户输入的学生信息,动态创建节点并按照尾插法插入到链表中。
主函数 main()
中调用函数 input()
创建链表,然后再使用 for
循环遍历链表并输出每个节点的数据。
代码
void input()
{
struct stud_node *q; // 定义临时指针变量 q,用于操作新的节点
int len=0; // 定义链表中节点数(即长度)的计数器,初始值为 0
q = (struct stud_node*)malloc(sizeof(struct stud_node)); // 在动态内存中分配新的节点空间
q->next = NULL; // 将指针成员变量初始化为 NULL,表示当前节点是末尾节点
scanf("%d ",&q->num); // 从键盘上读入学号
while ( q->num != 0 ) // 如果输入的学号不为 0,说明还有待创建的新节点
{
len++; // 计数器加 1,表示又成功创建了一个新节点
scanf("%s %d",q->name,&q->score); // 从键盘上读入姓名和分数,并存储到链表节点中
// 根据链表节点数 len 来判定是头插法还是尾插法
if ( len == 1 ) // 如果当前是第一个节点,直接将头指针和尾指针都指向该节点
{
head = q;
tail = q;
tail->next = NULL; // 将尾指针的 next 成员变量初始化为 NULL,表示当前节点是末尾节点
}
else // 否则,使用尾插法将新节点插入到链表末尾
{
tail->next = q; // 将尾指针指向的节点的 next 成员变量指向 q,即当前新节点
tail = q; // 尾指针更新为当前节点
tail->next = NULL; // 将尾指针的 next 成员变量初始化为 NULL,表示当前节点是末尾节点
}
q = (struct stud_node*)malloc(sizeof(struct stud_node)); // 在动态内存中分配新的节点空间
q->next = NULL; // 将指针成员变量初始化为 NULL,表示当前节点是末尾节点
scanf("%d ",&q->num); // 读取下一个学号,继续进行链表的创建
}
}
定义 struct stud_node 结构体,用于存储学号、姓名、分数以及指向下一个节点的指针。
定义链表的头指针和尾指针:struct stud_node *head, *tail。
在 main() 函数中,通过调用 input() 函数来创建链表;然后再通过 for 循环遍历链表并输出每个节点的数据。
-
函数 void input() 中首先创建了一个临时指针变量 q,用于操作新的节点,并在动态内存中分配新的节点空间。
-
通过 scanf() 函数从键盘上读取学号、姓名和分数等信息,并存储到新创建的节点中。
-
通过计数器 len 的值,判断是要使用头插法还是尾插法将新节点插入到链表中。如果当前新节点是第一个节点,那么直接将头指针和尾指针都指向该节点;否则,就使用尾插法将新节点插入到链表末尾。
-
重复上述步骤,直到读取的学号为 0,表示创建链表操作已完成。
整体代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct stud_node {
int num; // 学生学号
char name[20]; // 学生姓名
int score; // 学生成绩
struct stud_node *next; // 指向下一个节点的指针
};
struct stud_node *head, *tail; // 定义链表的头指针和尾指针
void input();
int main()
{
struct stud_node *p; // 定义临时指针变量 p
head = tail = NULL; // 头指针和尾指针初始值均为 NULL
input(); // 调用 input() 函数创建链表
for ( p = head; p != NULL; p = p->next ) // 循环遍历链表并输出每个节点的数据
printf("%d %s %d\n", p->num, p->name, p->score);
return 0;
}
void input()
{
struct stud_node *q; // 定义临时指针变量 q,用于操作新的节点
int len=0; // 定义链表中节点数(即长度)的计数器,初始值为 0
q = (struct stud_node*)malloc(sizeof(struct stud_node)); // 在动态内存中分配新的节点空间
q->next = NULL; // 将指针成员变量初始化为 NULL,表示当前节点是末尾节点
scanf("%d ",&q->num); // 从键盘上读入学号
while ( q->num != 0 ) // 如果输入的学号不为 0,说明还有待创建的新节点
{
len++; // 计数器加 1,表示又成功创建了一个新节点
scanf("%s %d",q->name,&q->score); // 从键盘上读入姓名和分数,并存储到链表节点中
// 根据链表节点数 len 来判定是头插法还是尾插法
if ( len == 1 ) // 如果当前是第一个节点,直接将头指针和尾指针都指向该节点
{
head = q;
tail = q;
tail->next = NULL; // 将尾指针的 next 成员变量初始化为 NULL,表示当前节点是末尾节点
}
else // 否则,使用尾插法将新节点插入到链表末尾
{
tail->next = q; // 将尾指针指向的节点的 next 成员变量指向 q,即当前新节点
tail = q; // 尾指针更新为当前节点
tail->next = NULL; // 将尾指针的 next 成员变量初始化为 NULL,表示当前节点是末尾节点
}
q = (struct stud_node*)malloc(sizeof(struct stud_node)); // 在动态内存中分配新的节点空间
q->next = NULL; // 将指针成员变量初始化为 NULL,表示当前节点是末尾节点
scanf("%d ",&q->num); // 读取下一个学号,继续进行链表的创建
}
}
需要注意的是: 在函数 input()
中使用 len
变量记录当前链表已有节点数,以便更新 head
和 tail
指针。如果当前节点是第一个节点(即 len == 1
),则将 head
和 tail
都指向该节点;否则,就直接使用尾插法将新节点附加到链表末尾。同时,循环中还需要在动态内存中分配新的节点空间,并通过 q = (struct stud_node*)malloc(sizeof(struct stud_node))
语句实现。
总结
该题考察指针和链表的相关知识点,涉及链表的创建
、遍历
、插入
等操作。
我是秋说,我们下次见。