氣泡排序演算法及其優化(BubbleSort)
阿新 • • 發佈:2019-02-09
氣泡排序算是排序演算法裡面的一種較為簡單的演算法,也是我接觸的第一種排序演算法,有升序與降序之分,如果面試的時候面試官問道這個題目,一定要問清楚是升序還是降序,這樣會給你加分。
下面,我以升序來講一下它的運作。
-
1、比較相鄰的元素。如果第一個比第二個大,就交換他們兩個。
-
2、對每一對相鄰元素作同樣的工作,從開始第一對到結尾的最後一對。在這一點,最後的元素應該會是最大的數。
-
3、針對所有的元素重複以上的步驟,除了最後一個。
-
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;
}