如何对存储F1车手的链表按积分及完赛名次实现排序?
F1车手信息链表排序实现
核心逻辑说明
排序完全按照给定规则实现:
- 第一排序键为
points总积分,积分越高排序越靠前 - 总积分相同时,从首站开始逐站对比
positions数组中存储的完赛名次,第一个出现名次更小(完赛位置更靠前)的车手排在前面
代码实现
基础定义补充
你已经有车手信息结构体,这里补充链表节点定义,和你现有逻辑完全兼容:
#define MAX 64 #define NRACES 24 // 可根据实际赛季分站数量调整 // 你已定义的车手信息结构体 struct element_struct { char name[MAX]; char team[MAX]; int points; int positions[NRACES]; }; // 单链表节点定义 typedef struct node { struct element_struct data; struct node *next; } DriverNode;
车手优先级比较函数
核心比较逻辑独立封装,不管选用什么排序算法都可以直接复用:
/** * 比较两个车手的排序优先级 * 返回值:1 代表a应排在b前;-1 代表b应排在a前;0 代表二者优先级一致 */ int compareDriver(struct element_struct a, struct element_struct b) { // 优先对比总积分 if (a.points != b.points) { return a.points > b.points ? 1 : -1; } // 积分相同逐站对比完赛名次 for (int i = 0; i < NRACES; i++) { // 若用0标记未参赛/无有效名次,直接跳过该站对比 // 如果你用99等大值标记无效名次,可删除下面这行判断 if (a.positions[i] == 0 || b.positions[i] == 0) continue; if (a.positions[i] != b.positions[i]) { return a.positions[i] < b.positions[i] ? 1 : -1; } } return 0; }
链表排序函数
针对单链表实现优化版冒泡排序,F1单赛季注册车手仅20人左右,小数据量下性能完全足够,实现简单不易出指针错误:
/** * 传入链表头指针的地址,原地完成链表排序 * 排序后头节点指向优先级最高的车手 */ void sortDriverList(DriverNode **head) { // 空链表或仅1个节点无需排序 if (*head == NULL || (*head)->next == NULL) { return; } int swapped; DriverNode *cur; DriverNode *sortedTail = NULL; // 标记已排序段的尾部,减少无效遍历 do { swapped = 0; cur = *head; while (cur->next != sortedTail) { // 当前节点优先级低于下一节点,直接交换两个节点存储的车手数据 if (compareDriver(cur->data, cur->next->data) < 0) { struct element_struct temp = cur->data; cur->data = cur->next->data; cur->next->data = temp; swapped = 1; } cur = cur->next; } sortedTail = cur; } while (swapped); }
注意事项
- 排序直接在原链表上交换节点数据,不需要修改节点的next指针,避免指针操作引发的内存错误。如果你的节点绑定了其他不可直接拷贝的资源,可以把交换数据的逻辑改成交换节点指针指向,核心比较逻辑不需要改动。
- 无效名次的判断逻辑可以根据你实际录入的规则调整:如果未参赛、退赛的记录统一存为远大于正常完赛名次的数值(比如99),不需要额外跳过,直接逐站对比即可,这类记录会自动排在同积分下完赛表现更好的车手后面。
- 每次新增车手、录入新分站的积分和名次后,调用一次
sortDriverList(&head)即可完成链表重排。
内容的提问来源于stack exchange,提问作者Poinsaett
相关产品推荐
相关产品推荐

