You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

嵌套链表创建求助:类与学生链表的插入逻辑实现问题

问题分析与修正方案

你的代码存在多个逻辑错误,导致嵌套链表的插入逻辑完全失效,下面是核心问题点和修正后的完整实现:

核心问题清单

  • 内存分配错误:malloc(sizeof(struct nodeClass*))分配的是指针大小,而非结构体本身的大小,会导致内存溢出。
  • 条件判断错误:用赋值运算符=代替比较运算符==,导致班级判断完全错误。
  • 班级节点重复创建:每个学生都新建一个班级节点,而非复用已存在的班级节点。
  • 学生链表未维护有序性:没有实现按成绩降序、同分学号升序的插入逻辑。
  • 空指针访问风险:当班级链表为空时,直接访问head->next会触发崩溃。
  • 未定义变量与语法错误:temp->classID=i;中的i未定义,函数参数、循环语法不完整。

修正后的完整代码

头文件(function.h)

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

// 学生节点结构体
struct nodeStudent
{
    int studentID;
    int midterm;
    struct nodeStudent *next;
};

// 班级节点结构体
struct nodeClass
{
    int classID;
    double classMidtermAverage;
    struct nodeClass *next;
    struct nodeStudent *studentPtr;
};

// 插入学生到对应班级的有序链表
void insert(struct nodeClass **head, int id, int midterm);
// 计算各班平均分
void computeClassAverage(struct nodeClass *head);
// 打印所有班级和学生信息
void printAll(struct nodeClass *head);

函数实现文件(function.c)

#include "function.h"

// 辅助函数:根据学生ID获取班级ID(66开头=1,77=2,88=3,99=4)
int getClassID(int studentID) {
    long classCode = studentID;
    // 提取前两位数字
    while (classCode >= 100) {
        classCode /= 10;
    }
    switch ((int)classCode) {
        case 66: return 1;
        case 77: return 2;
        case 88: return 3;
        case 99: return 4;
        default: return -1; // 无效班级
    }
}

// 辅助函数:将新学生插入到班级的有序学生链表(降序,同分学号小的在前)
struct nodeStudent* insertStudent(struct nodeStudent *studentHead, int id, int midterm) {
    struct nodeStudent *newNode = (struct nodeStudent*)malloc(sizeof(struct nodeStudent));
    newNode->studentID = id;
    newNode->midterm = midterm;
    newNode->next = NULL;

    // 空链表直接插入
    if (studentHead == NULL) {
        return newNode;
    }

    struct nodeStudent *prev = NULL;
    struct nodeStudent *curr = studentHead;

    // 找到插入位置:成绩更高,或成绩相同但学号更小
    while (curr != NULL && 
           (curr->midterm > midterm || 
            (curr->midterm == midterm && curr->studentID < id))) {
        prev = curr;
        curr = curr->next;
    }

    // 插入到链表头部
    if (prev == NULL) {
        newNode->next = studentHead;
        return newNode;
    }
    // 插入到中间或尾部
    prev->next = newNode;
    newNode->next = curr;
    return studentHead;
}

// 主插入函数:找到或创建班级节点,插入学生
void insert(struct nodeClass **head, int id, int midterm) {
    int classID = getClassID(id);
    if (classID == -1) {
        printf("无效学生ID:%d\n", id);
        return;
    }

    struct nodeClass *classNode = NULL;
    struct nodeClass *currClass = *head;

    // 查找已存在的班级节点
    while (currClass != NULL) {
        if (currClass->classID == classID) {
            classNode = currClass;
            break;
        }
        currClass = currClass->next;
    }

    // 班级不存在则创建新节点
    if (classNode == NULL) {
        classNode = (struct nodeClass*)malloc(sizeof(struct nodeClass));
        classNode->classID = classID;
        classNode->classMidtermAverage = 0.0;
        classNode->studentPtr = NULL;
        classNode->next = NULL;

        // 将新班级节点加入班级链表(头部插入)
        if (*head == NULL) {
            *head = classNode;
        } else {
            classNode->next = *head;
            *head = classNode;
        }
    }

    // 将学生插入到班级的有序学生链表
    classNode->studentPtr = insertStudent(classNode->studentPtr, id, midterm);
}

// 计算各班平均分
void computeClassAverage(struct nodeClass *head) {
    struct nodeClass *currClass = head;
    while (currClass != NULL) {
        int totalScore = 0;
        int studentCount = 0;
        struct nodeStudent *currStudent = currClass->studentPtr;

        while (currStudent != NULL) {
            totalScore += currStudent->midterm;
            studentCount++;
            currStudent = currStudent->next;
        }

        if (studentCount > 0) {
            currClass->classMidtermAverage = (double)totalScore / studentCount;
        } else {
            currClass->classMidtermAverage = 0.0;
        }

        currClass = currClass->next;
    }
}

// 打印所有信息
void printAll(struct nodeClass *head) {
    struct nodeClass *currClass = head;
    while (currClass != NULL) {
        printf("班级ID:%d,期中平均分:%.2f\n", 
               currClass->classID, currClass->classMidtermAverage);
        printf("学生列表(按成绩降序):\n");
        
        struct nodeStudent *currStudent = currClass->studentPtr;
        while (currStudent != NULL) {
            printf("学号:%d,成绩:%d\n", 
                   currStudent->studentID, currStudent->midterm);
            currStudent = currStudent->next;
        }
        printf("-------------------------\n");
        currClass = currClass->next;
    }
}

主函数文件(main.c)

#include "function.h"

int main()
{
    struct nodeClass *head = NULL;

    int id, midterm;
    printf("请输入学生ID和期中成绩(输入-1结束):\n");
    scanf("%d", &id);
    while(id != -1)
    {
        scanf("%d", &midterm);
        insert(&head, id, midterm);
        scanf("%d", &id);
    }

    computeClassAverage(head);
    printAll(head);

    // 注意:实际使用时需要添加内存释放逻辑,避免内存泄漏
    return 0;
}

关键逻辑说明

  1. 班级节点管理:每次插入学生时先查找对应班级,不存在则创建并加入班级链表,避免重复创建。
  2. 学生链表有序插入:通过遍历找到符合「成绩降序、同分学号升序」的插入位置,保证链表始终有序。
  3. 平均分计算:遍历每个班级的学生链表,累加总分和人数后计算平均值。
  4. 错误处理:对无效学生ID进行提示,避免程序崩溃。

内容的提问来源于stack exchange,提问作者userozz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 16:35:50