最近在複習數據結構,就寫一寫博客來記錄一下自己學習的路程。
一、冒泡排序很形象的就是最小的數字不斷往上冒泡,每冒泡一次最上面的數字就是最小的,這個過程很像在水裏冒泡一樣,所以就叫冒泡算法。
如上圖所示,這是經過了一次冒泡之後,2的位置從4變化到了1。所謂冒泡排序,最主要的思想就是兩兩比較,大的在下面小的在上面,這個過程也就是冒泡的過程。之後的冒泡過程也類似。經過6次冒泡,則成功將上面的集合變成有序集合。以下我用PHP代碼來實現一下(爲啥用PHP,因爲我堅信PHP是世界上最好的語言~~~有點沒底氣哈哈哈哈)
代碼1:
<?php
function maopao(&$list)
{
$count = count($list);
for ($i = 0; $i < $count; $i++) { //每循環一次就是一次冒泡的過程
for ($j = $count – 1; $j > $i; $j–) {
if ($list[$j – 1] > $list[$j]) {
swap($list[$j – 1], $list[$j]);
}
}
}
}
function swap(&$one, &$two)
{
$tmp = $one;
$one = $two;
$two = $tmp;
}
?>
輸入:輸入一個數組集合 (不考慮非法輸入) 輸出:一個有序的數組
優化:我們仔細想一下,如果要排序的集合本身就比較有序,那冒泡排序算法是不是依然進行n次冒泡進行比較,只是不交換數據而已,這樣子的話就做了很多無用功,我們是不是可以考慮在數據不交換的時候就停止比較了呢?因此,我們可以考慮添加一個標誌位,在進行比較的時候如果不交換數據就置爲true,這樣就可以控制在數據不交換的時候就不進行比較了。以下是PHP實現
代碼2:
<?php
function maopao(&$list)
{
$count = count($list);
static $flag = true;
for ($i = 0; $i < $count && $flag; $i++) { //每循環一次就是一次冒泡的過程
$flag = false;
for ($j = $count – 1; $j > $i; $j–) {
if ($list[$j – 1] > $list[$j]) {
swap($list[$j – 1], $list[$j]);
$flag = true;
}
}
}
return $list;
}
function swap(&$one, &$two)
{
$tmp = $one;
$one = $two;
$two = $tmp;
}
?>
只要添加一個標誌位來判斷它是否已經有序了,是否需要繼續冒泡,就可以減少不必要的比較,在性能方面還是提升了不少。這種性能在數據量比較大的時候還是能夠體現出來的。
時間複雜度:最好的情況下(在集合本身已經有序的情況下)冒泡排序只需要比較n-1次即可
最壞的情況下(在集合本身完全逆序的情況下)冒泡排序需要比較1+2+3+4+....n-1=n*(n-1)/2次
所以冒泡排序的時間複雜度爲O(n²),排序是穩定的
總結
冒泡排序很形象地就是小的數字不斷往上冒泡,最主要的思想就是兩兩交換,大的往下沉小的往上冒泡,每次冒泡最小的數字都冒泡到頂端。考慮到集合本身有序的情況,可以將有序之後做一些標識停止冒泡,這樣可以提升效率。