一、冒泡排序法概述
冒泡排序法的基本思想是:对待排序记录关键字从后往前(逆序)进行多遍扫描,当发现相邻两个关键字的次序与排序要求的规则不符时,就将这两个记录进行交换。这样,关键字较小的记录将逐渐从后面向前面移动,就像气泡在水中向上浮一样,所以该算法也称为气泡排序法。(提示:冒泡排序法也可使较大的记录排在前面)
假设需要排序的记录有n个,其关键字保存在数组a中,使用冒泡排序法,需对数组a进行n-1次扫描,完成排序操作,具体过程如下:
(1)将A[n]与A[n-1]进行比较,若A[n]<A[n-1],则交换两元素的位置。
(2)修改数组下标,使需要比较的两个元素为A[n-1]和A[n-2],重复步骤1,对这两个元素进行比较。重复这个过程,直到对A[2]和A[1]进行比较完为止。完成第1遍扫描,如下图所示。
3)经过第1遍扫描后,最小的元素已经像气泡一样“浮”到最上面,即位于元素A[1]中了。接下来重复前面的步骤,进行第2遍扫描,只是扫描到A[3]与A[2]进行比较完为止(因为A[1]中已经是最小的数据,不用再进行比较)。
(4)通过n-1遍扫描,前n-1个数都已经排序完成,最后一个元素A[n]肯定就是最大的数了。至此,完成排序操作。(提示:在以上描述中,为了让读者容易理解,假设数组元素是保存在A[1]~A[n]中的,由于C语言的数组元素下标是从0开始的,因此,需要修改数组的下标)
下面以一组待排序的数据演示冒泡排序的过程,假设有6个需要排序的数据序列如下:
69,65,90,37,92,6
通过冒泡排序法对这6个数据进行排序,其排序过程如下图所示。
第1遍从下向上扫描,首先对最后两个元素A[5]和A[4]进行比较,因92>6,将6上浮到A[4],92下沉到A[5]。接着将A[4]中的6和A[3]比较,6仍然较小,继续上浮至A[3]……这样经过n-1次比较,6上浮到A[0],完成第1遍扫描。此时A[0]中保存着当前数列中的最小数。完成最小数的冒泡过程。
第2遍扫描仍然从A[5]开始,至A[1]时结束,将37上浮到A[1]。
类似的方法,在第3遍扫描时,65上浮到A[2]中,至此,所有数都已按从小到大的顺序排列,但程序还需要进行第4遍和第5遍的扫描,因为程序并不知道后面的数据是否为有序的。
二、冒泡排序法实现
(1)冒泡排序法
void BubbleSort(int a[], int n)
{
int i, j, t;
for (i=0; i<n; i++) {
for (j=n-1; j>i; j--) {
if (a[j-1] > a[j]) {
t = a[j-1];
a[j-1] = a[j];
a[j] = t;
}
}
printf("第%d遍:", i+1);
for (j=0; j<n; j++)
printf("%d ", a[j]);
printf("\n");
}
}
(2)数组显示
void ShowData(int arr[], int n)
{
int i;
for (i=0; i<n; i++)
printf("%d ", arr[i]);
printf("\n");
return;
}
(3)冒泡排序法测试
#include <stdio.h>
#define ARRAYLEN 6
int main(int argc, char *argv[])
{
int i;
int a[ARRAYLEN] = {69, 65, 90, 37, 92, 6};
printf("原数据:");
ShowData(a, ARRAYLEN);
BubbleSort(a, ARRAYLEN);
printf("排序后:");
ShowData(a, ARRAYLEN);
return 0;
}
(4)运行结果
三、冒泡排序法改进
从上面的BubbleSort函数的过程可以看出,使用冒泡排序法对n个数据进行排序,一共需要进行n-1次的比较。如果本来就是有顺序的数据,也需要进行n-1次比较。这就造成了冒泡排序法的算法虽然简单,但效率较差。
为了提升冒泡排序法的效率,可对BubbleSort函数进行改进,当在某一遍扫描时,发现数据都已经按顺序排列了,就不再进行后面的扫描,而结束排序过程。
如何知道数据已经按顺序排好了呢?从上图可以看出,当第3遍扫描后,数据已经按顺序排列好了,第4遍扫描时将没有数据进行交换。因此,可以设置一个标志变量flag,在每一遍扫描之前将其值设置为0,在扫描数据过程中,若有数据交换,则设置其值为1。在一遍扫描完成之后,判断flag的值,若其值为0,表示在这一遍扫描中已经没有数据进行交换,数据已经按顺序排列,就不需要再进行后续的扫描了。
编程经验:为了提高排序效率,引进了一个标志变量。即通过内存空间使用上的增多来使程序执行效率得到提升,这称为“以空间换时间”。
(1)改进冒泡排序法的实现
void BubbleSortNew(int a[], int n)
{
int i, j, t, flag=0;
for (i=0; i<n; i++) {
for (j=n-1; j>i; j--) {
if (a[j-1] > a[j]) {
t = a[j-1];
a[j-1] = a[j];
a[j] = t;
flag = 1;
}
}
printf("第%d遍:", i+1);
for (j=0; j<n; j++)
printf("%d ", a[j]);
printf("\n");
if (flag == 0)
break;
else
flag = 0;
}
}
(2)改进冒泡排序法测试
#include <stdio.h>
#define ARRAYLEN 6
int main(int argc, char *argv[])
{
int i;
int a[ARRAYLEN] = {69, 65, 90, 37, 92, 6};
printf("原数据:");
ShowData(a, ARRAYLEN);
BubbleSortNew(a, ARRAYLEN);
printf("排序后:");
ShowData(a, ARRAYLEN);
return 0;
}
(3)运行结果
可以看出来,当第3遍扫描后,数据已经按顺序排列好了,第4遍扫描时将没有数据进行交换,就不再进行后面的扫描,而结束排序过程。
来源:oschina
链接:https://my.oschina.net/u/2294938/blog/687386