常用算法简述 -- 冒泡排序

写在前面

排序算法种类繁多,根据处理的数据规模与存储特点,可分为内部排序外部排序:前者处理的数据规模不大,内存足以容纳;后者处理的数据规模较大,必须将数据存放于外部存储器中,每次排序的时候需要访问外存。

根据输入的不同形式,分为脱机算法在线算法:前者待排序的数据是一次性给出的;而在云计算之类的环境中,待排序的数据是实时生成的,在排序算法开始运行时,数据并未完全就绪,而是随着排序算法本身的进行而逐步给出的。

另外,针对不同的体系结构,又分为串行并行两大类排序算法。根据算法是否采用随机策略,还有确定式和随机式之分。

排序算法需要关注比较次数交换次数这2个复杂度。

一、冒泡排序的原理

冒泡排序算法(英语:Bubble Sort)的原理如下:

  1. 从后往前依次比较相邻的元素。若是要按照升序排序,则后面的比前面的小,就交换这2个元素;降序则相反。
  2. 对每一对相邻元素作同样的工作,从第一对到最后一对。一轮比较交换下来,最后的元素就会是最小(或最大)的数了,这个数就不用参与后面的比较操作了。
  3. 针对所有的元素重复以上的步骤。
  4. 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

二、C++代码实现

2.1 基础版本

基础版完全按照上面的冒泡排序的原理来实现。主要点在于2次循环的作用,以及循环的开始和结束。

重点关注代码中的注释部分

// 功能:实现对int数组按升序排序
// 参数:
// data: int数组
// n: 数组元素的个数
// 返回值:
// 无
//
void BubbleSort_v1(int data[], int n) {
    int compare_times = 0; // 仅用于统计进行了多少次比较操作,与算法实现无关。
    int swap_times = 0;    // 仅用于统计进行了多少次交换操作,与算法实现无关。

    // 第一层循环表示需要冒多少个泡上来,n个数冒n-1个泡之后,顺序就确定下来了
    //
    for (int i = 0; i < n - 1; i++) { 
        // 第二层循环表示每个泡怎么冒,从后往前依次和相邻的元素两两比较
        //
        for (int j = n - 1; j > i; j--) {
            compare_times++;

            if (data[j] < data[j - 1]) {
                swap_times++;

                // data[j - 1]和data[j]交换
                //
                int temp = data[j];
                data[j] = data[j - 1];
                data[j - 1] = temp;
            }
        }
    }

    printf("比较:%d次,交换:%d次.\n", compare_times, swap_times);
}

2.2 带标记版本

基础版本针对已经有序的数组(如int a[] = {1,2,3,4,5,6}),仍然要进行完整的比较操作(虽然没有进行任何地数据交换),因为基础版本没有检测已有数据是否已经按照指定的顺序排列好了的功能。我们可以加入一个标记,如果一趟循环下来,一次交换操作都没有发生,则说明剩下的数据都已经按照指定的顺序排列好了,排序操作可以结束了。

// 功能:实现对int数组按升序排序
// 参数:
// data: int数组
// n: 数组元素的个数
// 返回值:
// 无
//
void BubbleSort_v2(int data[], int n) {
    int compare_times = 0; // 仅用于统计进行了多少次比较操作,与算法实现无关。
    int swap_times = 0;    // 仅用于统计进行了多少次交换操作,与算法实现无关。

    // 标记一个泡冒上来时,是否进行了交换操作。
    // 若一个泡冒上来,一次交换操作都没做,则说明剩下的元素都已经按照指定顺序(升序或降序)排好了。
    //
    bool has_swap = false; 

    // 第一层循环表示需要冒多少个泡上来,n个数冒n-1个泡之后,顺序就确定下来了
    //
    for (int i = 0; i < n - 1; i++) {
        has_swap = false;

        // 第二层循环表示每个泡怎么冒,从后往前依次和相邻的元素两两比较
        //
        for (int j = n - 1; j > i; j--) {
            compare_times++;

            if (data[j] < data[j - 1]) {

                // data[j - 1]和data[j]交换
                //
                int temp = data[j];
                data[j] = data[j - 1];
                data[j - 1] = temp;

                swap_times++;
                has_swap = true;
            }
        }

        // 一次交换操作都没做,则说明剩下的元素都已经按照指定顺序(升序或降序)排好了,结束排序操作。
        if (has_swap == false) {
            break;
        }
    }

    printf("比较:%d次,交换:%d次.\n", compare_times, swap_times);
}

你可能感兴趣的:(☆,算法基础)