冒泡排序(单向)

算法思想:
冒泡排序顾名思义就是整个过程就像气泡一样往上升,单向冒泡排序的基本思想是(假设由小到大排序):对于给定的n个记录,从第一个记录开始依次对相邻的两个记录进行比较,当前面的记录大于后面的记录时,交换其位置,进行一轮比较和换位后,n个记录中的最大记录将位于第n位;然后对前(n - 1)个记录进行第二轮比较;重复该过程直到进行比较的记录只剩下一个时为止。

#include <iostream>

void swap(int *a, int *b)
{
    int temp = *a;
    *a = *b;
    *b = temp;
}

// 最初的冒泡排序 (每一轮由上向下比较)
void bubbleSort(int arr[], int len)
{
    for (int i = 0; i < len - 1; i++) { // 需要len -1 趟排序,效率很低

        for (int j = 0; j < len - 1 - i; j++) { // 从头部开始比较,让每一轮比较中最大的数沉到最下方。

            if (arr[j] > arr[j + 1]) {
                swap(&arr[j], &arr[j + 1]);
            }
        }
    }
}

// 最初的冒泡排序(稍作调整,改变初始的比较位置和方向,每一轮由下向上比较)
void bubbleSort_1(int arr[], int len)
{
    for (int i = 0; i < len - 1; i++) { // 需要len -1 趟排序,效率很低

        for (int j = len - 1; j > i; j--) { // 从尾部开始比较,让每一轮比较中最小的数漂到最上方。

            if (arr[j] < arr[j - 1]) {
                swap(&arr[j], &arr[j - 1]);
            }
        }
    }
}


// 冒泡排序的第一次改进
void bubbleSort_2(int arr[], int len)
{
    bool flag; // 为什么在此处声明?防止循环中多次创建;
    for (int i = 0; i < len - 1; i++) {
        flag = true;

        for (int j = 0; j < len - 1 -i; j++) {
            if (arr[j] > arr[j + 1]) {
                swap(&arr[j], &arr[j + 1]);
                flag = false;
            }
        }

        if (flag) break;

    }
}


// 冒泡排序的第二次改进
void bubbleSort_3(int arr[], int len)
{
    bool flag;
    int lastSwapPos = len - 1;
    int lastSwapPosTemp = 0;

    for (int i = 0; i < len -1; i++) { // 控制 循环次数
        flag = true;

        for (int j = 0; j < lastSwapPos; j++) {  // 控制 比较次数
            if (arr[j] > arr[j + 1]) {
                swap(&arr[j], &arr[j + 1]);

                flag = false;
                lastSwapPosTemp = j; // 不能在此处执行 lastSwapPos = j; 这样会立刻改变内部for循环的范围,而我们是需要下次循环时才改变;
            }                        // lastSwapPosTemp 的值,在一次循环中是不断变化的,我们需要的是最终的值;
        }

        lastSwapPos = lastSwapPosTemp;  // 一次循环下来后,取得该次循环中最后一次交换的位置,并赋值给lastSwapPos;

        if (flag) break;

    }
}


int main(int argc, const char * argv[]) {
    int arr[] = {2,5,1,3,6,8};
    int len = sizeof(arr) / sizeof(int);

    // bubbleSort(arr, len);
    bubbleSort_1(arr, len);
    // bubbleSort_2(arr, len);
    // bubbleSort_3(arr, len);


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

冒泡排序总结:
(1)冒泡排序就是依次比较相邻两个元素,如果违反排序结果要求的就交换。

(2)普通的冒泡排序:最好、最坏和平均情况,时间复杂度都是O(n^2)。
bubble sort的定义是:进行n-1次排序,每次排序都要比较所有相邻的两个元素,但第i次排序时array尾部的i-1个元素都是排序好的,所以内层循环的长度是n-i-1(i是从0开始的)。

(3)第一次优化:最好情况时间复杂度为O(n),最坏和平均情况时间复杂度为O(n^2)
我们可以想到这种极端情况:array本身就是排序好的,但是依照如上算法,我们仍然要遍历n平方/2次。原因在于,我们没有机制检查数组是否是排序好的。解决办法就是加入标识项,如果发现一次内层循环没有经过任何交换,则说明array已经排序完毕。

(4)第二次优化:最好情况时间复杂度为O(n),最坏和平均情况时间复杂度为O(n^2)。
我们再想象一种极端情况:array长度为n,但是只有0,1元素未排序,那么依照上一种优化算法我们依然要遍历2*n次。原因在于我们内层循环长度的设定依据是,i次排序array的后i-1个元素是排序好的,但实际上i次排序的循环长度取决于i-1次排序时最后的交换位置,例如i-1次排序的最后交换位置是index,则表明index之后的元素都已经排序完毕,我们只需要记录这个Index就得到了下次(i次)的循环长度。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值