[C语言/PTA] 建立学生信息链表

简介: [C语言/PTA] 建立学生信息链表

题目要求

本题要求实现一个将输入的学生成绩组织成单向链表的简单函数。

函数接口定义

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 循环遍历链表并输出每个节点的数据。

1.函数 void input() 中首先创建了一个临时指针变量 q,用于操作新的节点,并在动态内存中分配新的节点空间。

2 通过 scanf() 函数从键盘上读取学号、姓名和分数等信息,并存储到新创建的节点中。

3.通过计数器 len 的值,判断是要使用头插法还是尾插法将新节点插入到链表中。如果当前新节点是第一个节点,那么直接将头指针和尾指针都指向该节点;否则,就使用尾插法将新节点插入到链表末尾。

4.重复上述步骤,直到读取的学号为 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 变量记录当前链表已有节点数,以便更新 headtail 指针。如果当前节点是第一个节点(即 len == 1),则将 headtail 都指向该节点;否则,就直接使用尾插法将新节点附加到链表末尾。同时,循环中还需要在动态内存中分配新的节点空间,并通过 q = (struct stud_node*)malloc(sizeof(struct stud_node)) 语句实现。


总结

该题考察指针和链表的相关知识点,涉及链表的创建遍历插入等操作。

我是秋说,我们下次见。

目录
相关文章
|
21天前
|
存储 算法 C语言
【C语言】深入浅出:C语言链表的全面解析
链表是一种重要的基础数据结构,适用于频繁的插入和删除操作。通过本篇详细讲解了单链表、双向链表和循环链表的概念和实现,以及各类常用操作的示例代码。掌握链表的使用对于理解更复杂的数据结构和算法具有重要意义。
178 6
|
25天前
|
存储 缓存 算法
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式,强调了合理选择数据结构的重要性,并通过案例分析展示了其在实际项目中的应用,旨在帮助读者提升编程能力。
46 5
|
1月前
|
存储 C语言
【数据结构】手把手教你单链表(c语言)(附源码)
本文介绍了单链表的基本概念、结构定义及其实现方法。单链表是一种内存地址不连续但逻辑顺序连续的数据结构,每个节点包含数据域和指针域。文章详细讲解了单链表的常见操作,如头插、尾插、头删、尾删、查找、指定位置插入和删除等,并提供了完整的C语言代码示例。通过学习单链表,可以更好地理解数据结构的底层逻辑,提高编程能力。
87 4
|
2月前
|
存储 缓存 C语言
C语言:链表和数组有什么区别
C语言中,链表和数组是两种常用的数据结构。数组是一种线性结构,元素在内存中连续存储,通过下标访问,适合随机访问且大小固定的情况。链表由一系列不连续的节点组成,每个节点存储数据和指向下一个节点的指针,适用于频繁插入和删除操作的场景,链表的大小可以动态变化。
|
2月前
|
C语言
无头链表再封装方式实现 (C语言描述)
如何在C语言中实现无头链表的再封装,包括创建节点和链表、插入和删除操作、查找和打印链表以及销毁链表的函数。
29 0
|
2月前
|
C语言
C语言链式结构之有头单链表再封装写法
本文介绍了如何使用C语言对有头单链表进行封装,包括节点的创建、链表的初始化、数据的插入和删除,以及链表的打印等功能。
21 1
|
1月前
|
C语言
【数据结构】双向带头循环链表(c语言)(附源码)
本文介绍了双向带头循环链表的概念和实现。双向带头循环链表具有三个关键点:双向、带头和循环。与单链表相比,它的头插、尾插、头删、尾删等操作的时间复杂度均为O(1),提高了运行效率。文章详细讲解了链表的结构定义、方法声明和实现,包括创建新节点、初始化、打印、判断是否为空、插入和删除节点等操作。最后提供了完整的代码示例。
61 0
|
2月前
|
C语言
无头链表二级指针方式实现(C语言描述)
本文介绍了如何在C语言中使用二级指针实现无头链表,并提供了创建节点、插入、删除、查找、销毁链表等操作的函数实现,以及一个示例程序来演示这些操作。
36 0
|
21天前
|
存储 C语言 开发者
【C语言】字符串操作函数详解
这些字符串操作函数在C语言中提供了强大的功能,帮助开发者有效地处理字符串数据。通过对每个函数的详细讲解、示例代码和表格说明,可以更好地理解如何使用这些函数进行各种字符串操作。如果在实际编程中遇到特定的字符串处理需求,可以参考这些函数和示例,灵活运用。
40 10
|
21天前
|
存储 程序员 C语言
【C语言】文件操作函数详解
C语言提供了一组标准库函数来处理文件操作,这些函数定义在 `<stdio.h>` 头文件中。文件操作包括文件的打开、读写、关闭以及文件属性的查询等。以下是常用文件操作函数的详细讲解,包括函数原型、参数说明、返回值说明、示例代码和表格汇总。
42 9