冒泡排序的分析以及優化


    以前學習C語言的時候接觸過兩種最簡單的排序方法,一個是冒泡排序法,另外一個是選擇排序法。(我認為凡是學習過編程的人都會接觸過!

     今天我想就冒泡排序法發表一下個人的觀點。也許有人問為什么只討論冒泡而不討論選擇排序?

我在這里闡述一下自己的理解:

1、時間復雜度:兩個算法在最壞的情況下的冒泡排序時間復雜度用大O表示是O(N^2),而選擇排序最壞情況是O(N) 在這點上也許看不出冒泡排序比選擇排序要好;

2、**穩定性:從這個角度上來講,冒泡排序的穩定性是要比選擇排序要高的,原因是冒泡排序在交換的過程中僅僅是兩個元素之間進行比較交換,不會破壞相同元素的原有順序,但是選擇排序就不一樣。這個不詳細說明。


       我看過在網上有許多人討論冒泡與選擇到底那個要好,爭論不休,我認為沒有必要,因為我覺得不同的算法都是要基於數據結構上來講的,現有數據結構而后才有相對適應的算法,不可能兩者調轉過來。我們今天討論的的冒泡排序的優化也能夠很大程度的減少時間復雜度。而且穩定性也相對高。何樂不為呢?


下面來回顧一下冒泡的最經典形式:

//程序演示只以5為例
#define N 5
int
main(void)
{
int array[N] = {5,4,3,2,1};
int i = 0,j = 0;
int temp = 0;
for(i = 0;i < N-1; i++)
{
for(j = 0;j < N-i-1;j++)
{
if(array[j] > array[j+1])
{
temp = array[j+1];
array[j+1] = array[j];
array[j] = temp;
}
}
}

}

在這里就不做過於簡單的分析了。我說兩點可以優化的地方:一個是運行時效率一個是減少時間復雜度,對於這兩者我們需要引入兩個知識點一個是位運算另一個是狀態機的思想。

第一點:位運算改善運行效率

對於編程有一定理解的人都會知道下面這一段代碼:

設 a = 1, b = 2;若不想使用第三個變量來使得a 和 b進行交換那么我們就可以用到位運算!


實現為:a   =   a  ^ b;           =>       a   ^=  b;

b   =   b  ^ a;           =>       b   ^=  a;

a   =   a  ^ b;       =>  a   ^=  b;

                                                      注:前面為全寫的表達式,后面是復合表達式。

       了解過計算機底層的朋友都一定知道,位運算要比變量之間的運算(加減乘除相互賦值)要快的許多!這段代碼能夠很大程度的改善運行時效率。就如同以前跑1000米是4分鍾。現在經過優化只需要3分鍾了。


第二點:狀態機思想改善時間復雜度(減少不必要的循環次數)

冒泡排序法就是無論任何情況,都是需要排序(N^2)次。無可避免,那么我們能否想一個辦法來使得它能盡最大能力的去減少循環的次數呢?那就要借用我們狀態機的思想:

具體思路是這樣:①程序一開始設置一個狀態變量state  =  -1

     ②當如果有元素需要比較時我們就可以讓state =  1;

     ③如果經過了一輪比較下來,我們的狀態變量state 還是為 -1 的話我們就可以判定為目標數組已經排好序!就可以結束程序,

這樣就能很大程度的減少不必要的循環次數!


經過位運算與狀態機的優化的冒泡排序法的代碼段如下:

int
main(void)
{
<span style="white-space:pre"></span>int array[N] = {5,4,3,2,1};
<span style="white-space:pre"></span>int i = 0,j = 0;
<span style="white-space:pre"></span>int state = -1;//定義狀態
<span style="white-space:pre"></span>for(i = 0;i < N-1; i++)
<span style="white-space:pre"></span>{
<span style="white-space:pre"></span>status = -1;// 每次進行大循環都定義為初始狀態
<span style="white-space:pre"></span>for(j = 0;j < N-i-1;j++)
<span style="white-space:pre"></span>{
<span style="white-space:pre"></span>if(array[j] > array[j+1])
<span style="white-space:pre"></span>{
<span style="white-space:pre"></span>state = 1;//一旦需要比較就改變狀態
<span style="white-space:pre"></span>array[j] ^= array[j+1];
<span style="white-space:pre"></span>array[j+1] ^= array[j];
<span style="white-space:pre"></span>array[j] ^= array[j+1];
<span style="white-space:pre"></span>}
<span style="white-space:pre"></span>}
<span style="white-space:pre"></span>if(state == -1) break;//如果執行過了一次大循環后狀//態還是為初始狀態那么就代表數組已經按預定的方式排好了序
<span style="white-space:pre"></span>}
}

觀點如果有瑕疵希望大家給予糾正!感謝大家的幫助!


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



冒泡排序及其算法優化分析 冒泡排序及其優化 優化的冒泡排序 冒泡排序及優化 冒泡排序及其優化 冒泡排序及其優化 冒泡排序及其優化 冒泡排序及優化 冒泡排序優化 如何優化冒泡排序?
 
粤ICP备14056181号  © 2014-2021 ITdaan.com