冒泡排序就是将待排序的元素看作是排列的“气泡”,较小的元素比较轻,从而要往上浮。在冒牌排序算法中需要对这个“气泡”序列处理若干遍,所谓的一遍处理,就是自底向上检查一遍这个序列,并时刻注意两个相邻元素的顺序是否正确。如果发现两个相邻元素逆序,即“轻”的元素在下面,就交换它们的位置。现在处理一遍后,“最轻”的元素就浮到了最高的位置;处理第二遍的时候,“次轻”的元素就浮到了次高的位置。在做作第二遍的时候,由于最高元素已经是“最轻”的元素,所以不必检查。一般地,第i遍处理时,不必检查第i高位以上的元素,因为经过前面i -1 遍的处理,它们已经是正确地排好序。
冒泡排序相对比较简单,只介绍第一遍的排序过程,这里指以 序列 :46 95 90 12 82 17 30 15 共 8 个元素为例
初始状态 : 46 95 90 12 82 17 30 15 从最后一个元素开始计算,红色表示当前搜索到的“最轻”元素,绿色表示相邻顺序错误需要交换的元素
比较一次 : 46 95 90 12 82 17 15 30 顺序相反,交换位置
比较两次 : 46 95 90 12 82 15 17 30 顺序相反,交换位置
比较三次 : 46 95 90 12 15 82 17 30 找到一个“更轻”的元素,不交换
比较四次 : 46 95 90 12 15 82 17 30 更新“最轻”的元素
比较五次 : 46 95 12 90 15 82 17 30 顺序相反,交换位置
比较六次 : 46 12 95 90 15 82 17 30 顺序相反,交换位置
比较七次 : 12 46 95 90 15 82 17 30 到达最高位置,结束第一遍
其他遍的处理过程类似,这里就不列出来了。
参考代码:
1 #include <stdio.h> 2 3 #define MAX_NUM 80 4 5 void bubblesort(int* a, int n) 6 { 7 int temp; 8 for (int i = 0; i < n; i++) 9 { 10 printf("第 %d 遍\n",i+1); 11 for(int j = n - 1; j > i; j--) 12 { 13 if(a[j] < a[j - 1]) 14 { 15 temp = a[j]; 16 a[j] = a[j - 1]; 17 a[j - 1] = temp; 18 19 for(int k = 0; k < n;k++) 20 { 21 printf("%d ",a[k]); 22 } 23 printf("\n"); 24 } 25 26 } 27 } 28 29 } 30 31 int main(int argc, char* argv[]) 32 { 33 int a[MAX_NUM]; 34 int n; 35 36 printf("Input total numbers: "); 37 scanf("%d",&n); 38 39 if( n > MAX_NUM ) n = MAX_NUM; 40 41 for(int i = 0; i < n;i++) 42 { 43 scanf("%d",&a[i]); 44 } 45 46 printf("排序步骤:\n"); 47 bubblesort(a,n); 48 49 return 0; 50 }
案例结果截图:
冒牌排序算法效率与稳定性分析
如果元素初始已排好序,则只需要一轮排序,比较次数n-1,移动次数为0.
如果元素处于逆序,则需要进行n-1遍排序,比较次数为(1+2+3+……+n-1)=n(n-1)/2
所以冒泡排序的实际爱你复杂度为O(n2),空间复杂度为O(1)。由于冒泡排序是根据输入序列的顺序的大小来决定排序后的位置,故是一种稳定的排序方法。
注:主要参考彭军、向毅主编的 《数据结构与算法》