按年龄优先、同年龄按字母序排序人员信息时输出异常求助
选择排序逻辑错误排查:年龄相同姓名字母序逆序问题
问题背景
需求:对人员信息列表按年龄升序排序,年龄相同时按姓名字母序升序排列。实现的C语言选择排序代码在大部分场景正常,但给定测试输入时,出现15岁的Mary排在Anna之前的错误结果。
测试输入
5 Gilbert 35 Anna 35 Anna 15 Mary 15 Joseph 40
原代码
#include <stdio.h> #include <string.h> struct people{ char name[30]; int age; }; int main(){ int n, i, j, min, tmp1; scanf("%d", &n); struct people person[n], temp; for(i = 0; i < n; i++){ scanf("%s%d", person[i].name, &(person[i].age)); } // SELECTION SORT for(i = 0; i < n - 1; i++){ min = i; for(j = i + 1; j < n; j++){ if (person[j].age < person[i].age || strcmp(person[j].name,person[min].name) < 0 && person[j].age == person[min].age){ min = j; } } if(min != i){ temp.age = person[i].age; person[i].age = person[min].age; person[min].age = temp.age; strcpy(temp.name, person[i].name); strcpy(person[i].name, person[min].name); strcpy(person[min].name, temp.name); } } for(i = 0; i < n; i++){ printf("%s %d\n", person[i].name, (person[i].age)); } }
错误现象
输出中Mary 15排在Anna 15之前,不符合姓名字母序升序的要求。
错误原因
核心问题出在选择排序的比较条件逻辑:
- 错误的比较基准:原代码第一个条件
person[j].age < person[i].age是将当前j位置的元素与轮次起始元素person[i]比较,而非当前记录的最小元素person[min]。这会导致当遇到同年龄的元素时,只要年龄小于person[i],就直接更新min,忽略了同年龄下的名字字典序比较。 - 以测试输入为例:当i=0(对应Gilbert 35),j遍历到Anna 15时,
15 < 35成立,min被设为2;继续遍历到Mary 15时,15 < 35依然成立,min被错误更新为3,最终导致Mary被交换到i=0的位置,出现逆序。
修复方案
修正比较逻辑,始终以当前min位置的元素为基准:
- 先判断j位置元素的年龄是否小于
min位置元素的年龄,是则更新min; - 若年龄相等,再判断j位置元素的名字字典序是否小于
min位置元素的名字,是则更新min。
同时优化结构体交换方式,直接交换整个结构体,避免分开复制字段的冗余和错误。
修复后的代码
#include <stdio.h> #include <string.h> struct people{ char name[30]; int age; }; int main(){ int n, i, j, min; scanf("%d", &n); struct people person[n], temp; for(i = 0; i < n; i++){ scanf("%s%d", person[i].name, &(person[i].age)); } // SELECTION SORT for(i = 0; i < n - 1; i++){ min = i; for(j = i + 1; j < n; j++){ // 正确的比较逻辑:先比年龄,年龄相等再比名字字典序 if (person[j].age < person[min].age || (person[j].age == person[min].age && strcmp(person[j].name, person[min].name) < 0)){ min = j; } } if(min != i){ temp = person[i]; // 直接交换整个结构体 person[i] = person[min]; person[min] = temp; } } for(i = 0; i < n; i++){ printf("%s %d\n", person[i].name, person[i].age); } return 0; }
内容的提问来源于stack exchange,提问作者Dachi_3210
相关产品推荐
相关产品推荐

