冒泡排序

本文详细介绍了冒泡排序的原理及步骤,并提供了C语言实现代码。同时探讨了冒泡排序的时间复杂度及其稳定性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

冒泡排序

冒泡排序(Bubble Sort),它的核心思想是:重复走访需要排序的数列(在本文中,我把每一次走访数列开始,一直到走访这一次结束,称为一趟),一次比较两个元素,如果它们的顺序错误(比如按照从小到大排列,发现前一个元素大于第二个,称为顺序错误),就把它们顺序交换过来。重复上述过程直到整个数列没有需要交换顺序的元素为止。

之所以称为冒泡排序,因为随着排序的进行,总会让较大的值“浮”到序列的顶端。

 

现在要对数列{1,5,3,2}进行从小到大排序。

 

第一趟:

  第一次:{1,5,3,2}----------首先拿出来前两个元素1和5进行比较,1小于5,因此不交换两者顺序。

  第二次:{1,3,5,2}----------第二次比较的时候,就要比较第二位和第三位,分别是5和3,5大于3,交换顺序。

  第三次:{1,3,2,5}----------第三次比较的时候,就要比较第三位和第四位,分别是5和2,5大于2,交换顺序。

 

  第一趟结束,确定了一个最大值:5,放在最后一位。冒泡排序中第一个泡已经浮上水面了。

 

 

第二趟:

       第一次: {1,3,2,5}-----------任然比较前两个元素1和3,1小于3,顺序不变

       第二次: {1,2,3,5}-----------比较第二位和第三位,分别是3和2,3大于2,交换顺序。

 

  第二趟这里已经结束了,第三个位置不需要再和第四个位置比较了,因为第一趟结束已经把最大数排到了最后一位(也就是第四位)。此时,又决定了数列中第二大数:3,放到了倒数第二位。

  第二个泡也浮出了水面,它是数列中的第二大,放在了倒数第二位。

 

 

第三趟:

       第一次: {1,2,3,5}------------比较数列中的前两位1和2,1小于2,顺序不变。

 

  第三趟也结束了,因为,第四、三位置的数,分别是最大数值和第二大数值,无需比较。

  此时,第三个泡也浮出了水面,它就是数列中的第三大数:2,排到倒数第三位(正数第二位),因此剩余的最小值1,排在第一位。

  冒泡排序到此结束。

 

 

结论与代码实现:

 

  因此,4个数,共走了3趟,其中第一趟3次,第二趟2次,第三趟1次。

  由上可推出,n个数,共需要走(n-1)趟,其中第 i 趟,需要比较的次数为 j =(n - i)

  

复制代码
#include<stdio.h>

//输出数组
void printArr(int a[], int n)
{
    for (int i = 0; i < n; i++)
    {
        printf("%d--", a[i]);
    }
    printf("\n");
}

//冒泡排序
void BubbleSort(int a[], int n)
{
    for (int i = 1; i <= n - 1; i++)//i为比较趟数,从第一趟开始,共需要(n-1)趟
    {
        for (int j = 1; j <= n - i; j++)//j为每一趟比较的次数,每趟最少比较一次,因此从1开始。第i趟,共需要比较(n-i)次,
        {
            if (a[j - 1] > a[j])//前面的大于后面的,换位
            {
                int temp = a[j];
                a[j] = a[j - 1];
                a[j - 1] = temp;
            }
        }
    }

    printArr(a, n);
}

void main()
{
    int a[4] = { 1, 3, 5, 2 };
    BubbleSort(a, 4);

    getchar();
}
复制代码

 (上述代码完全是按照本文的解释意思所写,可能与网上版本不太相同,其实核心思想是一样的。我的 i 和 j 从1开始,是为了方便理解趟数每趟比较的次数

 

 

 冒泡排序的改进:

 

  这里该有疑问了,当非最后一趟未发生一次顺序交换的时候,说明该数列已经排序OK了,那么剩下的每一趟,不都是在做无用功吗?

  因此,我们可以改进冒泡排序的算法。只需要在每一趟开始的时候,定义一个bool类型的标识变量sign,如果一趟结束了,标识符未发生改变,说明该数列已经排序完成。

复制代码
//冒泡排序
void BubbleSort(int a[], int n)
{
    bool sign;
    for (int i = 1; i <= n - 1; i++)//i为比较趟数,从第一趟开始,共需要(n-1)趟
    {
        sign = false;//在每一趟开始的时候,定义一个标识,为false。
        for (int j = 1; j <= n - i; j++)//j为每一趟比较的次数,每趟最少比较一次,因此从1开始。第i趟,共需要比较(n-i)次,
        {
            if (a[j - 1] > a[j])//前面的大于后面的,换位
            {
                int temp = a[j];
                a[j] = a[j - 1];
                a[j - 1] = temp;

                sign = true;
            }
        }
        if(sign==false)//如果一趟结束了,sign仍为false,说明这一趟一次交换也没进行,说明序列已经排序完成。
        {
            break;
        }
    }

    printArr(a, n);
}
复制代码

  正序数列(例如{1,2,3,4})走一趟,标识sign仍为false,break退出循环,共比较(n-1)次,因此最佳情况下,时间复杂度为n。

 

 

时间复杂度:

 

  最好情况,纯正序数列,比较(n-1)次,时间复杂度为n,

  普通情况,比较n(n-1)/2次,时间复杂度为n^2,

  平均时间复杂度:n^2。

 

 

稳定性:

  冒泡排序是一种稳定的排序。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值