【排序算法之冒泡排序】

文章目录

  • 概要:本期主要学习排序算法中的冒泡排序,会着重讲解算法的核心思想、时空复杂度分析以及代码的实现。
  • 一、冒泡排序
  • 二、核心思想
  • 三、时空复杂度分析
  • 四、代码实现
  • 结尾

概要:本期主要学习排序算法中的冒泡排序,会着重讲解算法的核心思想、时空复杂度分析以及代码的实现。

冒泡排序是一种常用的小数据量排序算法。

一、冒泡排序

为什么叫做冒泡排序?是因为这种排序的执行过程非常贴近于水中气泡上升至水面的过程。

二、核心思想

它会在一次冒泡的过程结束会将最一个元素排到它的最终位置。如此反复执行n轮冒泡,就可以实现n个元素的排序。

  1. 在每次的冒泡过程中,算法只会比较相邻的两个元素,并按照升序或者降序来决定是否交换它们的位置。
  2. 执行完n-1次的比对后,已经完成了将乱序中最大或者最小的元素排到它的最终位置。
  3. 执行n轮冒泡,即可确定n个元素的最终位置。
    这里先推荐一个算法可视化网站,可以直接跳转看一看冒泡排序的动态执行过程:)[链接]

三、时空复杂度分析

冒泡排序的时间复杂度可以从最好、最坏和平均三个层次来分析。

  1. 首先,最好的情况就是元素是顺序排好的,只需要一次冒泡,时间复杂度是O(n)。
  2. 然后,最坏的情况是元素的顺序是逆序的,时间复杂度是O(n^2)。
  3. 最后,对于平均复杂度的分析,我们可以通过对最好和最坏情况的逆序度取平均值来计算。最坏的情况,逆序度是n(n-1)/2,即需要交换元素n(n-1)/2次。最好的情况,有序度为n(n-1)/2,逆序度为0。然后我们去平均值,平均情况下,逆序度为n(n-1)/4,时间复杂度为O(n^2)级别。
    冒泡排序的空间消耗,主要在交换元素时需要申请额外的空间来存储元素,消耗的空间是常数级别,即空间复杂度为O(1)。因此,冒泡排序是一个原地排序算法。
    此外,如果我们在判断两个元素的大小顺序时,只有在两个元素大小不同时才交换元素,这样该元素的原本位置就不需要改变。因此,冒泡排序也是一个稳定算法。

四、代码实现

小数据量时,冒泡排序是一个不错的算法,实现简单,效果也很好。
下面展示C++的实现源码:

void SortFuncation::BubbleSort(QVector<int> _vec)
{
    if(_vec.length() <= 1)
    {
        return ;
    }
    QTime _beginTime = QTime::currentTime();
    qDebug()<<QString::fromLocal8Bit("开始时间:")<<_beginTime.toString("hh:mm:ss:zzzz");
    int _iLen = _vec.length();//记录vector的长度
    for(int i = 0;i < _iLen;i ++)
    {
        bool _hasSort = false;//标记是否还有需要排序元素
        for(int j = 0;j < _iLen-i-1;j ++)
        {
            if(_vec[j] > _vec[j+1])//设置升序排列
            {
                //交换元素
                int temp = _vec[j];
                _vec[j] = _vec[j+1];
                _vec[j+1] = temp;
                _hasSort = true;//更新标志位
            }
        }
        if(!_hasSort)//没有需要排序的元素,就提前退出循环
        {
            break;
        }
    }
    QTime _endTime = QTime::currentTime();
    qDebug()<<QString::fromLocal8Bit("结束时间:   ")<<_endTime.toString("hh:mm:ss:zzzz");
    qDebug()<<QString::fromLocal8Bit("冒泡排序耗时:")<<_beginTime.msecsTo(_endTime)<<"ms";
}

结尾

本期对于冒泡排序的学习就到这,下期我们学习插入排序:)

你可能感兴趣的:(算法,排序算法,算法,数据结构)