9.2.1冒泡排序(Bubble Sort)
冒泡排序是一种交换排序,它的基本思想是:两两比较相邻记录的关键字,如果他们顺序错误就把他们交换过来。这个算法的名字由来是由于越小的元素会经过交换慢慢浮到数列的顶端。
1、冒泡排序初级版
#include <stdio.h> #include <stdlib.h> void BubbleSort(int arr[], int n) { int i; int j; for(i=0; i<n; i++) { for(j=i+1; j<n; j++) { int temp; if(arr[i] > arr[j]) { temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } } } } void print(int arr[], int n) { int i; for(i=0; i<n; i++) { printf("%d ",arr[i]); } printf("\n"); } int main() { int arr[]={9, 1, 5, 8, 3, 7, 4, 6, 2}; int n = sizeof(arr)/sizeof(arr[0]); printf("排序前:\n"); print(arr, n); BubbleSort(arr, n); printf("排序后:\n"); print(arr, n); system("pause"); return 0; }
这段代码不是标准的冒泡排序算法,因为它不满足“两两比较相邻记录”的冒牌排序思想,它是最简单的交换的排序而已。
思路:让第1个位置的关键字和它后面的每一个关键字依次比较,如果大则交换,这样第1个位置的关键字在一次循环后一定变成最小值。不再搭理第一个位置了,让第2个位置的关键字和它后面的每一个关键字依次比较,如果打则交换,这样第2个位置的关键字在一次循环后一定变成次最小值。依次循环,直到所有关键字排序完成。
需要比较的次数:(n-1) + (n-2) + ...... + 2 + 1 = n(n-1)/2;
可能的最大交换次数:(n-1) + (n-2) + ...... + 2 + 1 = n(n-1)/2;
2、冒泡排序正宗版
#include <stdio.h> #include <stdlib.h> void BubbleSort(int arr[], int n) { int i; int j; for(i=0; i<n; i++) { // for(j=n-2; j>=i; j--) //一次循环后,最小的到漂浮到最上面。 for(j=0; j<n-1-i; j++) //一次循环后,最大的到沉到最下面。 { int temp; if(arr[j+1] < arr[j]) { temp = arr[j+1]; arr[j+1] = arr[j]; arr[j] = temp; } } } } void print(int arr[], int n) { int i; for(i=0; i<n; i++) { printf("%d ",arr[i]); } printf("\n"); } int main() { int arr[]={9, 1, 5, 8, 3, 7, 4, 6, 2}; int n = sizeof(arr)/sizeof(arr[0]); printf("排序前:\n"); print(arr, n); BubbleSort(arr, n); printf("排序后:\n"); print(arr, n); system("pause"); return 0; }
经过一次循环后,最小的数据如同气泡般慢慢浮到上面,因此成为冒泡排序。
或者 最大的数据慢慢沉到下面,也可以叫冒泡排序。
//for(j=n-2;j>=i; j--)//一次循环后,最小的到漂浮到最上面。
//for(j=0;j<n-1-i; j++) //一次循环后,最大的到沉到最下面。
需要比较的次数:(n-1) + (n-2) + ...... + 2 + 1 =n(n-1)/2;
可能的最大交换次数:(n-1) + (n-2) + ...... + 2 + 1 =n(n-1)/2;
3、冒泡排序优化算法
如果进行一次循环后,没有任何数据进行交换,则说明此序列已经有序,无需再进行后面的循环判断了。
#include <stdio.h> #include <stdlib.h> void BubbleSort(int arr[], int n) { int i; int j; bool flag = true; //优化算法 for(i=0; i<n && flag; i++) //优化算法 { flag = false; //优化算法 // for(j=n-2; j>=i; j--) //一次循环后,最小的到漂浮到最上面。 for(j=0; j<n-1-i; j++) //一次循环后,最大的到沉到最下面。 { int temp; if(arr[j+1] < arr[j]) { temp = arr[j+1]; arr[j+1] = arr[j]; arr[j] = temp; flag = true; //优化算法 } } } } void print(int arr[], int n) { int i; for(i=0; i<n; i++) { printf("%d ",arr[i]); } printf("\n"); } int main() { int arr[]={9, 1, 5, 8, 3, 7, 4, 6, 2}; int n = sizeof(arr)/sizeof(arr[0]); printf("排序前:\n"); print(arr, n); BubbleSort(arr, n); printf("排序后:\n"); print(arr, n); system("pause"); return 0; }
优化算法可以避免在已经有序的情况下进行无意义的循环判断
4 、冒泡排序复杂度分析
对优化后的代码分析,若排序的本身是正序排列(从小到大排列),则只需做n-1次比较,无需交换(最好情况)。若本身为反序排列(从大到小排列),则需做n(n-1)/2次比较,而且需做n(n-1)/2次交换(最坏情况)。