发布信息

冒泡排序遇上二维数组:一招搞定生产线综合排名

作者:本站编辑      2026-04-15 01:09:53     1
冒泡排序遇上二维数组:一招搞定生产线综合排名

还在为二维数组排序发愁?一篇文章带你打通任督二脉

在C语言学习中,冒泡排序是每个程序员的“初恋算法”,二维数组则是存储表格数据的“万能容器”。当二者相遇,能擦出怎样的火花?
今天,我们就用一个生产线评估案例,带你彻底搞懂如何用冒泡排序对二维数组进行整行排序。

一、先看场景:三条生产线,谁最优秀?

假设你是一家智能制造企业的工程师,三条生产线(编号1、2、3)生产直径规格为2.3mm的钢珠。每条线抽检50个钢珠,计算出三个关键指标:
产线
平均直径
准确度
精确度
1
2.31
0.01
0.08
2
2.28
0.02
0.12
3
2.32
0.02
0.06
现在需要综合排序:准确度权重0.6,精确度权重0.4,计算每条产线的综合得分,然后按得分从高到低排序输出。
如果用一维数组存储得分,排序后你根本不知道哪个得分对应哪条产线。二维数组 + 冒泡排序完美解决这个问题。

二、核心思想:整行交换,数据“连体婴”

我们把每条产线的编号综合得分存在一个 `ranking[3][2]` 的二维数组中:
ranking[0] = {10.86} // 产线1,得分0.86ranking[1] = {20.74} // 产线2,得分0.74ranking[2] = {30.92} // 产线3,得分0.92
  • 每行代表一个对象(产线)
  • 第0列存编号,第1列存得分
排序时,我们交换的是整行,而不是单独交换得分。这样编号和得分始终“绑定”在一起,永远不会乱。

三、冒泡排序回顾:相邻比较,不断冒泡

冒泡排序的核心思想:相邻元素两两比较,若顺序错误则交换,每一轮将最值“冒泡”到末尾
假设要对数组 `[70, 20, 80, 60, 50]` 进行降序(从大到小)排序:
  • 第1轮:70和20比较 → 不动;20和80比较 → 交换 → [70,80,20,60,50];20和60比较 → 交换 → [70,80,60,20,50];20和50比较 → 交换 → [70,80,60,50,20](最小值20沉底)
  • 第2轮、第3轮……直到完全有序。

四、结合二维数组:如何交换整行?

关键代码:比较相邻两行的第1列(得分),如果需要交换,则交换整行所有列。
// 假设 ranking[3][2] 已存好数据int n = 3// 3行for (int i = 0; i < n-1; i++) { for (int j = 0; j < n-i-1; j++) {   // 降序:如果前一行得分 < 后一行得分,交换   if (ranking[j][1] < ranking[j+1][1]) {     // 交换整行(两个元素:编号和得分)     double temp[2];     temp[0] = ranking[j][0];     temp[1] = ranking[j][1];     ranking[j][0] = ranking[j+1][0];     ranking[j][1] = ranking[j+1][1];     ranking[j+1][0] = temp[0];     ranking[j+1][1] = temp[1];    } }}
注意:这里用了一个临时一维数组 `temp[2]` 来暂存整行数据。你也可以逐个元素交换,但用数组更简洁。

五、完整实战代码(可直接运行)

下面是一个完整的程序:已知三条产线的准确度和精确度,计算综合得分并排序输出。
#include<stdio.h>#include<math.h>intmain(){ // 原始统计结果:每行[平均直径, 准确度, 精确度] double stats[3][3] = { {2.310.010.08}, {2.280.020.12}, {2.320.020.06} }; // 存放[产线编号, 综合得分] double ranking[3][2]; // 权重 double w_accuracy = 0.6; double w_precision = 0.4; double std_value = 2.3// 标准值 double ref_precision = 1.0// 参考标准差 // 计算每条产线的综合得分 for (int i = 0; i < 3; i++) {   ranking[i][0] = i + 1// 产线编号1,2,3   double accuracy = stats[i][1];   double precision = stats[i][2];   // 归一化得分(越小越好转为越大越好)   double acc_score = 1 - (accuracy / std_value);   double pre_score = 1 - (precision / ref_precision);   ranking[i][1] = w_accuracy * acc_score + w_precision * pre_score; } // 冒泡排序(降序,按得分) for (int i = 0; i < 2; i++) {   for (int j = 0; j < 2 - i; j++) {     if (ranking[j][1] < ranking[j+1][1]) {     // 交换整行     double temp[2];       temp[0] = ranking[j][0];       temp[1] = ranking[j][1];       ranking[j][0] = ranking[j+1][0];       ranking[j][1] = ranking[j+1][1];       ranking[j+1][0] = temp[0];       ranking[j+1][1] = temp[1];     }   } } // 输出排序结果 printf("排名\t产线编号\t综合得分\n"); for (int i = 0; i < 3; i++) {   printf("%d\t%d\t\t%.3f\n", i+1, (int)ranking[i][0], ranking[i][1]); } return 0;}

六、思考与扩展

1、如果统计指标增加到5个(比如再加CPK、偏度等),如何修改代码?
答:只需修改二维数组的列数,交换整行时用对应大小的临时数组即可,核心逻辑不变。
2、能否用一维数组实现?
可以,但需要同时维护多个一维数组(编号数组、得分数组),排序时要同步交换所有数组,代码冗长且易错。二维数组是更优雅的解决方案。
3、冒泡排序效率低(O(n²)),数据量大时怎么办?
可改用快速排序(`qsort`),但排序思路一致:比较的是得分,交换的是整行。理解冒泡是基础,日后迁移到任何排序算法都游刃有余。

七、总结

掌握了冒泡排序+二维数组的组合,你就掌握了多指标排序的核心技能。赶紧打开你的IDE,敲一遍上面的代码,亲自体验一下整行交换的威力吧!

相关内容 查看全部