最近看了一下氣泡排序這個經典的演算法,在網上也看到了很多改進氣泡排序演算法的方式,這裡總結一下:
氣泡排序最簡單的實現方式如下(我用php來實現,用其他語言也是一樣的):
for($i=0;$i
<$arr_count;$i++)
}}
例如:[ 3 , 1 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 ]—-針對這個陣列我們按照基本氣泡排序演算法,需要迴圈count([ 3 , 1 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 ])輪,也就是10輪。
第一輪的排序結果如下:[1,3,4,5,6,7,8,9,10,11]
第二輪的排序結果如下:[1,3,4,5,6,7,8,9,10,11]
第三輪的排序結果如下:[1,3,4,5,6,7,8,9,10,11]
第….輪的排序結果如下:[1,3,4,5,6,7,8,9,10,11]
第十輪的排序結果如下:[1,3,4,5,6,7,8,9,10,11]
通過上面的介紹,會發現,上面的陣列其實在第一輪排序後就已經將陣列排序好了。後面的幾輪排序其實都是無用功。也就是說下面的**白白走了9遍,一點作用都沒發生。
上面的白白執行9遍的**中,每一遍都能在(n-1)的資料比較,如果陣列的長度n極大,這個消耗還是很嚴重的。所以我們首先要解決一下這個問題,怎麼才能不造成無謂的資料比較的資源浪費。
優化策略:在程式中新增標識,用於記錄每次外迴圈過程中,是否發生了資料的交換。如果沒有發生資料的交換,就意味者在上一輪的外迴圈過程中,資料已經排序完成,不需要繼續迴圈比較資料了,我們直接break掉就可以了。如果還存在這資料的交換,就意味著在之前的外部迴圈中,資料還沒有排序好,這一輪排序操作或者接下來的排序操作才可以完成排序工作,我們還需要進行下一輪的排序來完成排序。
$arr_count = count($rand_arr);
for($i=0;$i
<$arr_count;$i++)
}if($flag)
}
其實,在進行資料排序的過程中,隨著排序的進行,資料逐漸從無序變為有序,出現上面情況的可能性會逐步的增高的。
好了,說完上面的問題,咱們再來看下面的問題。當氣泡排序的外部迴圈每執行一次,就會將最大值(最小值)交換到陣列的最前端或者陣列的最後端,直接看下面的例子。
經過第一輪排序以後會得到以下的結果:[ 4 , 6 , 2 , 7 , 8 , 0, 9 ] —-也就是說,我們再第一輪求出的最大值9,並且將這個值交換到陣列的左部第一的位置上
經過第二輪排序以後會得到以下的結果:[ 4 , 6 , 2 , 7 , 0 , 8 , 9 ] —-也就是說,我們再第二輪求出的次最大值8,並且將這個值交換到陣列的左部第二的位置上
依此類推,我們可以發現,每一輪迴圈完畢,都能求出某個位置上的應有的資料,並且完成交換。那麼也就是說陣列的左部(右部)逐漸變得有序,且有序部分的長度等於外部迴圈進行的輪數。既然陣列的左部(右部)逐漸變得有序,那麼每次迴圈過程中,我們就不需要再比較陣列的左部(右部)的有序的部分了。
優化策略:新增乙個變數來記錄某次外部迴圈過程中最後發生的資料交換的位置。使用上面記錄的位置來作為下一次外部迴圈中的內部迴圈的終止條件,這樣就能減少不必要資料比較過程。**如下:
$arr_count = count($rand_arr);
$last_pos = $arr_count; //記錄每一次外部迴圈過程中,最後進行資料交換的位置
$next_pos = $arr_count; //記錄每一次資料交換的位置
for($i=0;$i
<$arr_count;$i++)
}//如果該輪迴圈得到的最後的資料交換位置等於上一輪迴圈得到的資料交換的位置,就意味著陣列全部有序了
if($last_pos == $next_pos)else
}
解決了上面的問題,我們還能不能進一步的提高冒泡演算法的排序速度嘛?答案是可以的。我們可以採用雙向排序的方式,進一步加快排序的速度。看下面的實現的例子:
陣列: [ 4 , 3 , 6 , 5 , 9 , 0 , 1 , 7 ]
雙向排序之正向排序(從左到右排序):[ 3 , 4 , 5 , 6 , 0 , 1 , 7 , 9] —計算出陣列的最大值9,並將元素移動到陣列的最右邊
雙向排序之逆向排序(從右到左排序):[ 0 , 3 , 4 , 5 , 6 , 1 , 7 , 9] —計算出陣列的最小值0,並將元素移動到陣列的最左邊
第一次迴圈過程,計算出最大值並將該值移動到陣列最右邊,計算出最小值並將該值移動到陣列的最左邊。第二次迴圈過程中,計算出第二大的值並將資料移動到陣列右邊第二個的位置,計算出第二小的值並將資料移動到陣列左邊第二個的位置。也會說在一次雙向排序迴圈過程中,求出陣列左邊以及陣列右邊各個位置響應的元素,並且移動到響應的位置。
具體的實現**如下:
$arr_count = count($rand_arr);
$index = 0; //從左到右排序過程中起始的位置
$first_pos = 0; //從右到左排序過程中最後進行資料交換的位置
$up = $arr_count-1; //從左到右排序過程中結束的位置
$last_pos = $up; //從左到右排序過程中最後進行資料交換的位置
while($up >= $index)
}if($up == $last_pos)
$up = $last_pos;
//從尾部開始掃瞄
for($j=$up;$j>1;$j--)
}if($index == $first_pos)
$index = $first_pos;
}
網上也有大神對這幾種排序做了對比,用了1000個隨機數組
沒有進行優化,冒泡執行的時間38.826741201211
第一次優化後,冒泡執行的時間36.326452970505
第二次優化後,冒泡執行的時間24.916656017303
第三次優化後,冒泡執行的時間20.908751010895
氣泡排序以及優化
排序 1.穩定的排序演算法 2.不穩定的排序演算法 3.比較排序 元素之間的次序依賴它們之間的比較,每個數需要與其他數進行比較才能確定自己的位置。比較典型的比較排序有快速排序,歸併排序,堆排序,氣泡排序。4非比較排序 非比較排序只要確定每個元素之前的已有元素個數即可,經過一次遍歷便可以解決。排序 1...
氣泡排序以及優化
氣泡排序是新手小白學的第乙個排序方法,複雜度很高。那麼如何在氣泡排序的基礎上對其進行優化?我們給一組資料 9,5,6,7,5,3 第一次冒泡 9和5交換位置 5,9,6,7,5,3 9和6交換位置 5,6,9,7,5,3 9和7交換位置 5,6,7,9,5,3 9和5交換位置 5,6,7,5,9,3...
氣泡排序以及優化
最近需要用到氣泡排序,所以翻出來研究一下。氣泡排序的基礎其實就是元素交換,是一種極其簡單的排序演算法。話不多說,直接上 1 include 2 void bubble sort int arr,int len 315 16 17 1819int main 20 22int len int sizeo...