1. 程式人生 > >氣泡排序演算法及其優化(BubbleSort)

氣泡排序演算法及其優化(BubbleSort)

氣泡排序算是排序演算法裡面的一種較為簡單的演算法,也是我接觸的第一種排序演算法,有升序與降序之分,如果面試的時候面試官問道這個題目,一定要問清楚是升序還是降序,這樣會給你加分。

下面,我以升序來講一下它的運作。

  1. 1、比較相鄰的元素。如果第一個比第二個大,就交換他們兩個。

  2. 2、對每一對相鄰元素作同樣的工作,從開始第一對到結尾的最後一對。在這一點,最後的元素應該會是最大的數。

  3. 3、針對所有的元素重複以上的步驟,除了最後一個。

  4. 4、持續每次對越來越少的元素重複上面的步驟,直到沒有任何一對數字需要比較。

演算法思想圖:

  假設有個數列為 3 1 5 6 2,我們以升序對它進行排序。

氣泡排序第一版:


#include<stdio.h>
#include<stdlib.h>
void bubblesort(int *p,int len)
{
int i = 0;
int j = 0;
for(i = 0;i<len-1;i++)
{
/*每排序一趟,則至少有一個元素已經有序,
用 j<len-i-1 可以縮小排序範圍 */
for(j = 0;j<len -1-i;j++)
{
/*當前面的元素大於後面的元素時,交換位置*/
if(p[j]>p[j+1])
{
int tmp = p[j];
p[j] = p[j+1];
p[j+1] = tmp;
    }
}
}
}
int main()
{
int num[5]={3,1,5,6,2};
int i=0;
bubblesort(num,5);
for(i=0;i<5;i++)
{
printf("%d ",num[i]);
}
return 0;
} 
printf("%d ",num[i]);
}
return 0;
} 

當數列在基本有序的情況下時,例如數列:

                                                   1 2 3 5 4 6 7 8 9 10 

在第一趟排序 5 和 4 交換之後數列就已經有序了,所以剩下的8趟排序就是多餘的。再用上面的演算法處理這個數列,效率就顯得低了。所以,我們對它新增一個檢視flag。

氣泡排序優化版:


#include<stdio.h>
#include<stdlib.h>
void bubblesort(int *p,int len)
{
int i = 0;
int j = 0;
int flag;  
for(i = 0;i<len-1;i++)//
{
/*flag初始化為0*/
flag = 0;
/*每排序一趟,則至少有一個元素已經有序,
用 j<len-i-1 可以縮小排序範圍 */
for(j = 0;j<len -1-i;j++)
{
/*當前面的元素大於後面的元素時,交換位置*/
if(p[j]>p[j+1])
{
int tmp = p[j];
p[j] = p[j+1];
p[j+1] = tmp;
/*若程式進入if語句,則必然會發生交換,
當發生交換時把flag置成 1 */ 
flag = 1;
}
}
/*判斷,如果flag=0,說明上一趟排序沒有發生交換,
數列已經有序,break*/ 
if(flag == 0)
{
break;
}
}
}
int main()
{
int num[10]={1,2,3,5,4,6,7,8,9,10};
int i=0;
bubblesort(num,10);
for(i=0;i<10;i++)
 { printf("%d ",num[i]);
   }
return 0;
  } 

其實上面的演算法還可以進行優化,來看下面一組資料:1 2 7 4 6 3 5 8 9

首先我們要知道:

    當它每完成一趟排序的適合,我們記住它最後一次交換的位置,也就是flag最後一次置1的位置,我們假設這個位置為P,P之後的元素已經有序,P之前的元素還可能無序。所以我們只需要對P之前的元素再進行排序就可以了

我們將前面無序區的數列當做一個新的數列,把它的新長度傳給第一層迴圈,這樣就可以大大減少迴圈次數,提升效率。

氣泡排序最終優化版:


#include<stdio.h>
#include<stdlib.h>
 void bubblesort(int *p,int len)
 {
 	int i = 0;
 	int j = 0;
 	int k = len-1; 
 	int m = 0;
 	int flag;  
 	/*用k來儲存新的判斷條件*/ 
 	for(i = 0;i<k;i++)
 	{
	 /*flag初始化為0*/
 	 flag = 0;
 	 m = 0;
 	/*每排序一趟,則至少有一個元素已經有序,
		 用 j<len-i-1 可以縮小排序範圍 */
	for(j = 0;j<len-1-i;j++)
	{
	/*當前面的元素大於後面的元素時,交換位置*/
        if(p[j]>p[j+1])
	{
	int tmp = p[j];
	p[j] = p[j+1];
	p[j+1] = tmp;
	 /*若程式進入if語句,則必然會發生交換,
		    當發生交換時把flag置成 1 */ 
	flag = 1;
	/*記住最後一次交換的位置*/ 
        m = j;
	 }
	}	
	/*判斷,如果flag=0,說明上一趟排序沒有發生交換,
	數列已經有序,break*/ 
	if(flag == 0)
	{
	 break;
	}
	/*將新的長度賦值給k*/	
	k = m;	
	}
 }
 int main()
 {
   int num[10]={1,2,7,4,6,3,5,8,9};
   int i=0;
   bubblesort(num,9);
   for(i=0;i<9;i++)
   {
    printf("%d ",num[i]);
   }
 	return 0;
  }