常用的排序算法系列
冒泡排序
这期讲个比较简单实现的排序算法,在数据规模较小的时候,比如数组长度可能不到5000之类的(不同语言有不同差异),用简单的算法可能会比复杂算法更优。
因为简单算法在规模小的情况下,表现出来的劣势并不明显,复杂算法也可能只是快那么零点零几秒,而复杂算法多数是需要占用更多的空间资源的,因此简单场景下,我们不妨就用简单的排序算法。
冒泡排序
这个是初学者多数接触到的第一个算法。这个算法很简单,我当初最开始学的时候,记的是 “两个循环,相邻比较”,然后把这个算法记住的。
冒泡排序法的本质,就是逐个用相邻比较交换的方法,从数组头开始检查到待检查的数组尾。每一轮排序结束之后,尾巴就会多一个排好的数,就像冒泡一样把这个数冒了出来。
比如我们手里有一个数组a
[5,8,6,4,12,5]
现在需要把它从小到大排序,那么我们就开始逐个相邻比较交换,相邻的数据里面,如果是大的在前,小的在后,我们就交换一下。
首先,a[0]=5 < a[1] =8, 不理
a[1] > a[2] 交换一下两个数
变成了
[5,6,8,4,12,5]
继续检查
a[2] > a[3],交换一下两个数
变成了
[5,6,4,8,12,5]
a[3] < a[4] ,不理
a[4] > a[5], 交换一下
变成了
[5,6,4,8,5,12]
这时候,我们完成了第一轮的排序,成功的冒出了一个最大的数【12】,因此我们第二轮的排序就不需要去管这个最末已经冒出来的数据了。
假设我们的数组长度是 n,第一位是0,那么数组最后一位就是 n-1,倒数第二位是 n-2 。
第一轮,我们两两比较的前数,是从 0 一直到 n-2 的,也就是从第一位到倒数第二位,而后数是从1一直到 n-1,两个是相邻的关系。
第二轮的前数就会从0 一直到 n-3 (因为前一轮冒出了一个), 后数则一直等于前数加1。
第三轮的前数就会从0 一直到 n-4 (前几轮一共冒出了两个)
如此递推,那么最后一层就是 从0 一直到1,只比较一次,
这整个过程,一共有n-1轮,根据上面的递推关系会发现,第 i 轮,前数都是从 0 到 n -1- i 的,所以这里面就可以用两个循环来处理。
外层循环令变量为 i ,是从0 遍历到 n-1 ,也就是表示这里面的 n-1 轮。
内层循环令变量为 j ,是从0 遍历到 n-1-i ,也就是表示每一轮这里面的逐个前后两个相邻数进行比较。
在内层循环里,如果 a[j] > a[j+1], (目的是从小排到大的情况),说明应该把小数放到更前面,所以交换这两个数。
这个就是冒泡排序的全部过程了。
实现代码
/** 冒泡排序
* @param array $ar
* @param null $len
*/
function bubble(array & $ar, $len = null)
{
if ($len === null) {
$len = sizeof($ar);
}
for ($i = 0; $i < $len-1; $i++) {
for ($j = 0; $j < $len-$i-1; $j++) {
if ($ar[$j] > $ar[$j+1]) {//swap
echo "swap [$j]--[";
echo $j+1;
echo ']';
echo "<br/>";
$t = $ar[$j];
$ar[$j] = $ar[$j+1];
$ar[$j+1] = $t;
}
}
print_r(json_encode($ar));
echo "<br/>";
}
}
热门评论
留给初学者一个小思考题,如果我想要每一轮的排序,有一个小的数冒到最前面来,请问需要怎么做呢?