You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

如何为关联分数的学生ID数组实现计数排序并同步ID位置

解决学生分数排序时ID同步绑定的问题

我明白你的痛点——你需要对学生的分数进行排序,同时让对应的学生ID牢牢绑定到分数的最终位置上,而不是单独排序分数导致ID和分数脱节。你尝试用计数排序但遇到了卡点,咱们一步步来搞定这个问题。

首先,先明确核心:我们不能只单独操作分数数组,必须把**学生ID和分数作为一个整体(也就是你的SResult结构体)**来进行排序,这样才能保证两者的对应关系不丢失。下面是调整后的计数排序实现,完全适配你的结构体场景:

完整实现代码

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

// 定义你的学生成绩结构体
struct SResult {
    char id[10]; // 假设ID长度足够容纳所有学生ID
    int score;
};

// 针对结构体数组的计数排序(按分数升序)
void countSortStudents(struct SResult arr[], int n) {
    // 第一步:确定分数的取值范围,找最大、最小值
    int max_score = arr[0].score;
    int min_score = arr[0].score;
    for (int i = 1; i < n; i++) {
        if (arr[i].score > max_score) max_score = arr[i].score;
        if (arr[i].score < min_score) min_score = arr[i].score;
    }
    int score_range = max_score - min_score + 1;

    // 创建计数数组和临时输出数组
    int* count_arr = (int*)calloc(score_range, sizeof(int));
    struct SResult* output_arr = (struct SResult*)malloc(n * sizeof(struct SResult));

    // 统计每个分数出现的次数
    for (int i = 0; i < n; i++) {
        count_arr[arr[i].score - min_score]++;
    }

    // 将计数数组转换为前缀和,用来确定每个分数在输出数组中的最终位置
    for (int i = 1; i < score_range; i++) {
        count_arr[i] += count_arr[i - 1];
    }

    // 从后往前遍历原数组,把结构体元素放到输出数组的正确位置
    // 从后往前是为了保证相同分数的学生保持原相对顺序(稳定排序)
    for (int i = n - 1; i >= 0; i--) {
        int target_idx = count_arr[arr[i].score - min_score] - 1;
        // 复制整个结构体(ID+分数)到输出数组
        strcpy(output_arr[target_idx].id, arr[i].id);
        output_arr[target_idx].score = arr[i].score;
        count_arr[arr[i].score - min_score]--;
    }

    // 将排序后的结果复制回原数组
    for (int i = 0; i < n; i++) {
        strcpy(arr[i].id, output_arr[i].id);
        arr[i].score = output_arr[i].score;
    }

    // 释放动态分配的内存
    free(count_arr);
    free(output_arr);
}

// 测试函数
int main() {
    struct SResult sample[] = {
        {"A1234", 10}, {"A1239", 5}, {"A1394", 7}, {"A1434", 3},
        {"A1454", 5}, {"A2884", 7}, {"A3235", 7}, {"A4334", 9},
        {"A4884", 2}, {"A6934", 5}, {"A7265", 7}, {"A9559", 3}
    };
    int student_count = sizeof(sample) / sizeof(sample[0]);

    printf("排序前:\n");
    for (int i = 0; i < student_count; i++) {
        printf("ID: %s | 分数: %d\n", sample[i].id, sample[i].score);
    }

    countSortStudents(sample, student_count);

    printf("\n排序后(按分数升序):\n");
    for (int i = 0; i < student_count; i++) {
        printf("ID: %s | 分数: %d\n", sample[i].id, sample[i].score);
    }

    return 0;
}

关键注意点

  1. 绑定结构体整体操作:整个排序过程都是针对SResult结构体进行的,而不是单独提取分数排序,这样ID和分数的对应关系从始至终不会断开。
  2. 字符串复制处理:因为结构体里的ID是字符数组,不能直接用=赋值,必须用strcpy来完成ID的复制。
  3. 稳定排序保障:从后往前遍历原数组的操作,能让相同分数的学生保持他们在原数组中的相对顺序(比如原数组里先出现的5分学生,排序后依然排在同分数的前面),如果不需要稳定排序,也可以改成从前往后遍历。
  4. 降序排序调整:如果需要按分数降序排列,只需要修改计数数组的前缀和计算逻辑(从后往前累加),并调整遍历方向即可,具体修改可以参考代码里的注释思路。

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

火山引擎 最新活动