排序——冒泡排序法

1、冒泡排序法概述算法

    冒泡排序法的基本思想是:对待排序记录关键字从后往前(逆序)进行多遍扫描,当发现相邻两个关键字的次序与排序要求的规则不符时,就将这两个记录进行交换。这样,关键字较小的记录将逐渐从后面向前面移动,就像气泡在水中向上浮同样,因此该算法也称为气泡排序法。(提示:冒泡排序法也可以使较大的记录排在前面)
    假设须要排序的记录有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遍的扫描,由于程序并不知道后面的数据是否为有序的。code

2、冒泡排序法实现排序

(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)数组显示io

void ShowData(int arr[], int n)
{
    int i;
    for (i=0; i<n; i++)
        printf("%d ", arr[i]);
    printf("\n");

    return;
}

(3)冒泡排序法测试class

#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)运行结果

3、冒泡排序法改进

    从上面的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遍扫描时将没有数据进行交换,就再也不进行后面的扫描,而结束排序过程。

相关文章
相关标签/搜索