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

C语言二分查找学生排名程序返回异常值问题求助

C程序二分查找排名问题修复

问题描述

我要编写一个C程序,输入共4行:前三行格式为「姓名#分数」,第四行为待查找的学生姓名,程序需返回该学生的排名(按分数降序排序后的位置)。我将输入数据存入结构体并按分数降序排序,但二分查找部分总是返回不符合预期的值,恳请帮忙解决。

原代码

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

typedef struct {
    char name[11];
    int score;
} report;

int main() {
    int n = 3;
    report student[n];
    for (int i = 0; i < 3; i++) {
        scanf("%[^\#]#%d", student[i].name, &student[i].score);
    }

    // 输入要查找的姓名
    char search[11];
    scanf("%s", search);

    // 冒泡排序(按分数降序)
    for (int a = 0; a < n - 1; a++) {
        for (int b = 0; b < n - 1 - a; b++) {
            if (student[b].score < student[b+1].score) {
                report temp;
                strcpy(temp.name, student[b].name);
                temp.score = student[b].score;

                strcpy(student[b].name, student[b+1].name);
                student[b].score = student[b+1].score;

                strcpy(student[b+1].name, temp.name);
                student[b+1].score = temp.score;
            }
        }
    }

    // 二分查找
    int left = 0;
    int right = n - 1;
    int middleIndex;
    int rank;
    while (left <= right ) {
        middleIndex = (int)(left + right) / 2;
        if (strcmp(student[middleIndex].name, search) == 0) {
            rank = middleIndex+1;
            break;
        } else if (strcmp(student[middleIndex].name, search) > 0) {
            left = middleIndex + 1;
        } else if (strcmp(student[middleIndex].name,search) < 0) {
            right = middleIndex - 1;
        }
    }

    // 输出排名
    printf("%d", rank);
    return 0;
}

示例输入

Jojo#40
Ray#60
Liz#80
Jojo

排序后结构体数组:[{Liz, 80}, {Ray, 60}, {Jojo,40}]
预期输出:3


错误原因

二分查找的核心前提是查找序列必须与比较逻辑的排序规则一致。你现在的数组是按分数降序排序的,但二分查找时却用姓名的字典序来调整左右边界——两者完全不匹配,导致查找逻辑彻底失效。比如示例中排序后的姓名顺序是Liz、Ray、Jojo,而姓名的字典序是Jojo < Liz < Ray,和数组顺序完全相反,二分查找根本无法定位到目标。


修复方案

方案1:替换二分查找为遍历查找(推荐)

由于只有3个学生,遍历查找的效率完全足够,实现简单且不易出错。将原二分查找部分替换为:

int rank = -1; // 初始化标记未找到的情况
for (int i = 0; i < n; i++) {
    if (strcmp(student[i].name, search) == 0) {
        rank = i + 1;
        break;
    }
}

// 处理未找到的情况(可选)
if (rank == -1) {
    printf("未找到该学生");
} else {
    printf("%d", rank);
}

方案2:调整排序规则适配二分查找(若坚持用二分)

如果一定要使用二分查找,需要将数组按姓名的字典序排序,同时保留分数排名信息。例如,可以在结构体中额外添加rank字段,先按分数排序确定排名,再按姓名排序以支持二分查找:

typedef struct {
    char name[11];
    int score;
    int rank; // 新增排名字段
} report;

// 先按分数降序排序,确定排名
for (int a = 0; a < n - 1; a++) {
    // 原冒泡排序逻辑不变
}
// 给每个学生赋值排名
for (int i = 0; i < n; i++) {
    student[i].rank = i + 1;
}

// 再按姓名字典序排序,适配二分查找
for (int a = 0; a < n - 1; a++) {
    for (int b = 0; b < n - 1 - a; b++) {
        if (strcmp(student[b].name, student[b+1].name) > 0) {
            report temp = student[b];
            student[b] = student[b+1];
            student[b+1] = temp;
        }
    }
}

// 此时二分查找逻辑生效,找到后输出rank字段即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 15:15:29