冒泡排序

Posted wasi-991017

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了冒泡排序相关的知识,希望对你有一定的参考价值。














算法例题

用随机函数生成16个2位正整数(10~99),利用冒泡排序法将其排序。


算法思路

书面概括

  1. 设待排序的元素存放在数组r[1...m]中。首先将第一个元素的关键字和第二个元素的关键字进行比较,若为逆序(即L.r[1].key > L.r[2].key),则交换两个记录。然后比较第二个元素和第三个元素的关键字。以此类推,直至第n-1个元素和第n个元素的关键字进行过比较为止。上述过程称作第一趟冒泡排序,其结果使得关键字最大的元素被安置到最后一个元素的位置;
  2. 然后进行第二趟冒泡排序,对前n-1个元素进行同样的操作,其结果是使关键字次大的元素被安置到第n-1个元素的位置上;
  3. 重复上述比较和交换过程,第i趟是从L.r[1]到L.r[n-i+1]依次比较相邻两个元素的关键字,并在“逆序”时交换相邻元素,其结果是这n-i+1个元素中关键字最大的元素被交换到第n-i+1的位置上。直到在某一趟排序过程中没有进行过交换元素的操作,说明该序列已全部达到排序要求,则完成排序。


个人概括

每一趟排序通过无序序列中元素的比较和交换位置,将无序序列中最大的元素移到最后,将其更新为有序序列中的最小元素。
1.引入一个无序序列

技术图片

2.第一趟

  • 比较第一个元素和第二个元素
  • 第一个元素小于第二个元素,无需交换

技术图片


  • 比较第二个元素和第三个元素
  • 第二个元素大于第三个元素,进行交换

技术图片
技术图片
技术图片

  • (省略中间比较交换n步)比较第十二个元素和第十三个元素
  • 第十二个元素大于第十三个元素,进行交换
  • 将排在无序序列中最后一个元素,即第十三个元素,更新为有序序列

技术图片
技术图片
技术图片
技术图片



3.第二趟

  • (省略中间比较交换n步)将排在无序序列中最后一个元素,即第十二个元素,更新为有序序列

技术图片


4.第三趟

  • (省略中间比较交换n步)将排在无序序列中最后一个元素,即第十一个元素,更新为有序序列

技术图片



5.(省略n步)最后一趟
技术图片

考虑情况

  1. 某一趟排序(不只是第一趟)没有移动任何一个元素,则说明该无序序列实际上是有序序列,代码中使用监视哨进行监视;
  2. 每一趟排序都会确定无序序列中一个最大元素为有序序列中的最小元素,即每一趟排序后都会少一次比较次数。

算法效率

  • 最好情况:待排序序列为顺序序列
    • 比较次数KCN:n-1;
    • 移动次数RMN:0;
  • 最坏情况:待排序序列为逆序序列
    • 比较次数KCN:(n - 1) + (n - 2) + ... + 1 ≈ n2/2;
    • 移动次数RMN:3((n - 1) + (n - 2) + ... + 1) ≈ 3n2/2;

所以时间复杂度为O(n2)
下面的代码是我按照自己的思路进行编写的,算法效率能达到应有的程度。

空间复杂度为O(1),移动时需要辅助空间。

算法特点

  • 稳定排序;
  • 链式存储结构也适合;
  • 移动次数较多;
  • 更适合于初始记录基本有序(正序)的情况,当序列完全无序,尤其是逆序,且元素过多,时间复杂度会大大提高。


算法代码

#include<iostream>
#include<ctime>
using namespace std;

void BubbleSort(int* array, int n)
{
    //记录比较次数和移动次数
    int recordMove = 0;
    int recordCompare = 0;

    //监视哨
    //标记排序是否发生交换
    //若不发生交换(为0)
    //则排序完成
    int flag = 1;

    while (flag == 1 && n - 1 > 0)
    {
        //若没有发生交换
        //flag为0,则不会发生下一趟排序
        flag = 0;
        for (int i = 1; i < n; i++)
        {
            recordCompare++;

            //如果前者大于后者
            //进行交换
            //监视哨置1
            if (array[i] > array[i + 1])
            {
                flag = 1;

                //array[0]为辅助空间
                array[0] = array[i];
                recordMove++;
                array[i] = array[i + 1];
                recordMove++;
                array[i + 1] = array[0];
                recordMove++;
            }
        }

        //每趟排序后
        //下一趟排序的比较次数都-1
        n--;

        cout << "第" << 16 - n << "趟排序:" << endl;
        for (int j = 1; j <= 16; j++)
        {
            if (j == n + 1) cout << "[ ";
            cout << array[j] << " ";
            if (j == 16) cout << "]";
        }
        cout << endl << endl;
    }
    cout << "比较次数:" << recordCompare << endl;
    cout << "移动次数:" << recordMove << endl << endl;
}

int main()
{
    //生成随机16个正整数
    int positiveInteger[17];
    time_t t;
    srand((unsigned)time(&t));
    cout << "生成16个2位正整数:" << endl;
    for (int i = 1; i <= 16; i++)
    {
        positiveInteger[i] = (rand() % (100 - 10)) + 10;
        cout << positiveInteger[i] << " ";
    }
    cout << endl << endl;

    //冒泡排序
    BubbleSort(positiveInteger, 16);

    cout << "排序后数组:" << endl;
    for (int i = 1; i <= 16; i++)
    {
        cout << positiveInteger[i] << " ";
    }
    cout << endl << endl;


    system("pause");
    return 0;
}


运行结果

技术图片


以上是关于冒泡排序的主要内容,如果未能解决你的问题,请参考以下文章

java冒泡排序法代码

python代码实现鸡尾酒排序(双向冒泡排序)

冒泡排序python代码

视频+图文+动画详解冒泡排序

交换排序(冒泡排序快速排序的算法思想及代码实现)

C语言冒泡排序。