• 冒泡排序


    冒泡排序算法是一个非常经典和直观的排序算法,是许多数据结构初学者入门的排序法。它是一个稳定的排序算法,所需要的空间复杂度为O(1),但是时间复杂度却是O(n^2)的,当然冒泡排序算法还存在优化的版本(后面会讲到),使得可以在一定程度上优化冒泡排序算法。

    算法原理: 

    举个升序栗子:加入对于一个有10个整数的乱序数组int arr[10] = { 12,4,9,102,85,6,42,78,36,8,25 },冒泡排序算法总共有两层for循环,首先所要做的第一步就是先建立第一层for循环,逐步找出这十个数的最大数并通过不断交换元素,将最大数放到数组最后面。我们所建立的这第一层循环主要是用来寻找数组中的最大数,它是放置在内层循环中。

    实例内层循环代码:

    int arr[11] = { 12,4,9,102,85,6,42,78,36,8,25,-1 };
        int length = sizeof(arr) / sizeof(arr[0]) - 1;
        for (int begin = 1; begin <= length; begin++) {
            if (arr[begin] < arr[begin - 1])
            {
                int temp = arr[begin];
                arr[begin] = arr[begin - 1];
                arr[begin - 1] = temp;
            }
        }

    可以看到,这一层循环只能做到将整数数组的最大值找出来,却无法做到将整个数组按升序的顺序排列好。但是如果顺着思路往下思考,对于这样一个有十个整数的数组一次循环可以找出数组最大值并将其放到数组最后,那么是不是可以循环重复上述步骤九次(因为第九次循环后只剩下一个最小的数组元素了,没必要再循环比较一次,故只进行九次循环),就可以将所有的元素排好。我们可以将这个循环放到外面进行控制内层循环,另一方面由于内层每循环一次会将一个最大数放到后面,我们称之为已经排序好的数据,这样就可以修改内层循环终止条件,使得可以自适应的减少内层循环的比较次数,具体分析,见下面代码示例:

    完整冒泡排序示例:

     1 int arr[10] = { 12,4,9,102,85,6,42,78,36,8,25 };
     2     int length = sizeof(arr) / sizeof(arr[0]) - 1;
     3     for (int end = length; end > 0; end--)  //控制循环次数,循环九轮
     4     {
     5         //内层循环,找出每一轮最大值,放到后面
     6         for (int begin = 1; begin <= end; begin++)  //将循环终止田间修改为 begin <= end,end每次减一,这样可以跳过已排序好的数组元素
     7         {
     8             if (arr[begin] < arr[begin - 1])
     9             {
    10                 int temp = arr[begin];
    11                 arr[begin] = arr[begin - 1];
    12                 arr[begin - 1] = temp;
    1314             }
    15         }
    16     }

    优化后的冒泡排序:

    上面的乱序整数数组有一个特点就是:整个数组是完全乱序的,这是比较常见的。当然我们可能还会遇到以下这种情况:

    第一种情况是刚开始数组也是完全乱序的,但是经过几轮排序后尾部提前出现了局部有序,或者说数组一开始,尾部就是有序的,那么我们可以想办法去避免对后面提前出现有序现象的数组元素进行重复比较的操作。
    尾部示例:
    int arr[12] = { 12,4,9,10,8,6,4,16,18,24,25,36,40 };该数组从a[7]元素就出现尾部完全有序的现象,因此上一轮的循环去标记最后一次进行元素交换的位置,更新下一轮的外层循环截止条件,来避免重复比较的现象的出现。

    优化后的冒泡排序示例代码:

    int arr[12] = { 12,4,9,102,85,6,42,78,36,8,25,-1 };
        int length = sizeof(arr) / sizeof(arr[0]) - 1;
        for (int end = length; end > 0; end--)
        {
            int sortedIndex = 0;
            for (int begin = 1; begin <= end; begin++)
            {
                if (arr[begin] < arr[begin - 1])
                {
                    int temp = arr[begin];
                    arr[begin] = arr[begin - 1];
                    arr[begin - 1] = temp;
                    sortedIndex = begin; //如果进入if条件判断,则更新sortedIndex
                }
            }
            end = sortedIndex; //内层循环结束,将最新的sortedIndex赋值给外部循环截止条件end
        }
  • 相关阅读:
    单例对象
    G1回收算法
    Java锁
    VUE开发
    Java线程池
    Java线程状态
    什么是进程,什么是线程
    maven 常用命令
    linux启动脚本,暂停脚本
    delphi---控件使用
  • 原文地址:https://www.cnblogs.com/liyaning/p/15900639.html
Copyright © 2020-2023  润新知