- 比较两个相邻的数据,将值大的数据交换到右边
- 时间复杂度O(n^2)
- 空间复杂度O(1)
- 稳定排序
一、基础版本
$array = [
5, 1, 6, 7, 9
];
for ($i = 0; $i < count($array) - 1; $i ++ ) {// 控制冒泡的 轮数 N-1 轮
for ($j = 0; $j < count($array) - $i - 1; $j ++) { // 每轮需要比较的次数
if ($array[$j] > $array[$j+1]) { // 相邻两个数据比较大小
// 数据交换
$t = $array[$j];
$array[$j] = $array[$j+1];
$array[$j+1] = $t;
}
}
}
var_dump(implode(',', $array));
//string(9) "1,5,6,7,9"
二、优化版本
1. 从减少循环 轮数 上优化
$array = [
5, 1, 6, 7, 9
];
for ($i = 0; $i < count($array) - 1; $i ++ ) {// 控制冒泡的 轮数 N-1 轮
//标志本轮是否发生了未发生数据交换
$f = true;
for ($j = 0; $j < count($array) - $i - 1; $j ++) { // 每轮需要比较的次数
if ($array[$j] > $array[$j+1]) { // 相邻两个数据比较大小
// 数据交换
$t = $array[$j];
$array[$j] = $array[$j+1];
$array[$j+1] = $t;
//交换了数据,标志更改
$f = false;
}
}
// 如果某一轮比较后,未发生过数据交换
// 表示数据已经有序
if ($f) {
break;
}
}
var_dump(implode(',', $array));
//string(9) "1,5,6,7,9"
2. 从减少 每轮的比较次数 优化
分析冒泡排序的流程,每一轮最后一次交换的位置之后的数据都是有序的,考虑,如果某一轮的最后一次的交换位置知道了,那么下一轮比较,只需比较位置之前的数据即可。
举例:对于原始数据 5,1,6,7,9,当第一轮交换时,5和1交换过后,数据变成1,5,6,7,9
此时,5和剩下的数据6,7,9,不会发生数据交换,实际上数据已经有序了,$p = 0; $len = 0;下一轮比较,$f = true,直接跳出循环,完成整个排序
本例子下面的改进,只需两轮就完成了整个序列的排序
$array = [
5, 1, 6, 7, 9
];
//记录最后一次的交换的位置
$p = 0;
$len = count($array) - 1;
for ($i = 0; $i < count($array) - 1; $i ++ ) {// 控制冒泡的 轮数 N-1 轮
//标志本轮是否发生了未发生数据交换
$f = true;
// 注意这里的变化, $j < $len
for ($j = 0; $j < $len; $j ++) { // 每轮需要比较的次数
if ($array[$j] > $array[$j+1]) { // 相邻两个数据比较大小
// 数据交换
$t = $array[$j];
$array[$j] = $array[$j+1];
$array[$j+1] = $t;
//交换了数据,标志更改
$f = false;
//赋值当前的交换的位置
$p = $j;
}
}
//将本轮最后一次的交换位置
//作为下一轮的截止条件
$len = $p;
// 如果某一轮比较后,未发生过数据交换
// 表示数据已经有序
if ($f) {
break;
}
}
var_dump(implode(',', $array));
//string(9) "1,5,6,7,9"