冒泡排序(Bubble Sort)
一种最简单的交换排序方法,它通过两两比较相邻记录的关键字,如果发生逆序,则进行交换,从而使关键字小的记录如气泡一般逐渐往上‘漂移’(左移),或者使关键字大的记录如石块一样逐渐向下‘坠落’(右移)。
算法思想:
从数组头部开始,不断比较相邻的两个元素的大小,让较大的元素逐渐往后移动(交换两个元素的值),直到数组的末尾。经过第一轮的比较,就可以找到最大的元素,并将它移动到最后一个位置。第一轮结束后,继续第二轮。仍然从数组头部开始比较,让较大的元素逐渐往后移动,直到数组的倒数第二个元素为止。经过第二轮的比较,就可以找到次大的元素,并将它放到倒数第二个位置。以此类推,进行 n-1(n 为数组长度)轮“冒泡”后,就可以将所有的元素都排列好。
实例分析:
4
|
6
|
1
|
5
|
7
|
3
|
2
|
8
|

第一趟排序: 最右边我们得到了最大的泡 8
第二趟排序: 倒数第二个元素是除了8之外最大的元素 7
第三趟排序:倒数第三个与元素是除了8 7之外的最大的元素 6
一次类推我们只需要进行到第七趟排序 数列的第一个元素必定是最小的泡了因为最大的都已经往前冒了
得到的第一个元素肯定是最小的
分析一下代码:
#include <stdio.h> #include <stdlib.h> #define L 8 //输出数列 void pri_sort(char *a, int l) { int i; for (i = 0; i < l; i++) { if (i == l - 1) printf("%d ", a[i]); else printf("%d ", a[i]); } } int main() { char sortN[L] = { 4,6,1,5,7,3,2,8 }; char temp; int i, j; /*从小到大的冒泡排序*/ /*长度为L的数列只需要L-1趟排序因为最后一趟只有一个元素而且它是最小的在它后面的都比它大 */ for (i = 1; i < L; i++) { printf("第%d趟排序: ", i); //j=0 每趟从数列的头部开始比较 L-i是去掉尾部已经泡出来的泡 因为它们已经是有序的了 for (j = 0; j < L-i; j++) { if (sortN[j]>sortN[j+1]) { temp = sortN[j]; sortN[j] = sortN[j + 1]; sortN[j + 1] = temp; } pri_sort(sortN, L); } } system("pause"); }
每一趟排序的过程如下:

从上面的代码我们发现第5趟的排序 数列已经排序完成剩下的第6,7趟其实是不必要的排序 所以我们设置一个flag变量 如果本次排序没有进行下一次就没有必要进行了
刚才的例子是从左往右冒泡
#include <stdio.h> #include <stdlib.h> #define L 8 void pri_sort(char *a, int l) { int i; for (i = 0; i < l; i++) { if (i == l - 1) printf("%d ", a[i]); else printf("%d ", a[i]); } } int main() { char sortN[L] = { 4,6,1,5,7,3,2,8 }; char temp; int i, j; /*从小到大的冒泡排序*/ /*长度为L的数列只需要L-1趟排序因为最后一趟只有一个元素而且它是最小的在它后面的都比它大*/ for (i = 1; i < L; i++) { int flag = 0;//标志 printf("第%d趟排序: ", i); for (j = 0; j < L-i; j++) { if (sortN[j]>sortN[j+1]) { temp = sortN[j]; sortN[j] = sortN[j + 1]; sortN[j + 1] = temp; flag = 1; } pri_sort(sortN, L); } //本趟没有排序操作 已经排序完成 退出 if (!flag) break; } system("pause"); }
从大到小的冒泡排序 原理是一样的:
if (sortN[j]<sortN[j+1])//小的往后冒就OK了
我们可以从右往左冒:
#include <stdio.h> #include <stdlib.h> #define L 8 void pri_sort(char *a, int l) { int i; for (i = 0; i < l; i++) { if (i == l - 1) printf("%d ", a[i]); else printf("%d ", a[i]); } } int main() { char sortN[L] = { 4,6,1,5,7,3,2,8 }; char temp; int i, j; /*从小到大的冒泡排序*/ /*长度为L的数列只需要L-1趟排序因为最后一趟只有一个元素而且它是最小的在它后面的都比它大*/ for (i = L-1; i >=0; i--) { int flag = 0;//标志 printf("第%d趟排序: ", L-i); for (j = i; j >= 0; j--) { if (sortN[j]<sortN[j-1]) { temp = sortN[j]; sortN[j] = sortN[j - 1]; sortN[j - 1] = temp; flag = 1; } pri_sort(sortN, L); } //本趟没有排序操作 已经排序完成 退出 if (!flag) break; } system("pause"); }
算法特点:
(1).稳定排序
(2).可用于链式储存结构
(3).移动记录次数较多,算法平均时间性能比直接插入排序差。当初始记录无序,n比较大是,此算法不宜采用。