zoukankan      html  css  js  c++  java
  • 排序算法(2)-冒泡排序及优化

    1.冒泡排序

    之前写过一个排序算法(1),其中总结了冒泡排序 .
    冒泡排序的思想,是把相邻的元素两两比较,根据大小来交换元素的位置,每经过一轮的扫描,就会确定出一个最大的元素,即是一个元素有序.

    原始的冒泡排序是稳定排序(如果一个数组中存在几个相同的元素,排序前后的相同元素的前后顺序不会发生变更,则认为排序是稳定的)。由于该排序算法的每一轮要遍历所有元素,轮转的次数和元素数量相当,所以时间复杂度是O(N^2) 。

    代码如下:

     /**
         * @description 冒泡排序
         * @author zhangdi
         * @param arr
         * @description : 两两比较,大的往后放; 每一次比较完成之后,下一次就少比较一个元素
         *              第一次比较有0个元素不比较;第二次有一个元素不需要比较;第三次有两个元素不需要比较;
         *              共需要比较arr.length-1次
         */
        public static void BubbleSort(int[] arr) {
    
            int temp;// 临时变量
            if (arr == null || arr.length == 0)
                return;
            for (int i = 0; i < arr.length - 1; i++) { // 表示趟数,一共arr.length-1次。
                for (int j = arr.length - 1; j > i; j--) {
    
                    if (arr[j] < arr[j - 1]) {
                        temp = arr[j];
                        arr[j] = arr[j - 1];
                        arr[j - 1] = temp;
                    }
                }
            }
        }
    
        /**
         * @description 冒泡排序-2
         * @param arr
         * @author zhangdi
         */
        public static void BubbleSort2(int[] arr) {
    
            int temp;// 临时变量
            if (arr == null || arr.length == 0)
                return;
            for (int i = 0; i < arr.length - 1; i++) { // 表示趟数,一共arr.length-1次。
                for (int j = 0; j < arr.length - 1 - i; j++) {
    
                    if (arr[j] > arr[j + 1]) {
                        temp = arr[j];
                        arr[j] = arr[j + 1];
                        arr[j + 1] = temp;
                    }
                }
            }
        }
    

    2冒泡排序改进

    现在我们思考一下,会发现这个算法还有优化的空间,比如说但是一个数组前一半部分已经是有序的,当某轮中没有发生元素交换,就可以确定,整个数组已经是有序的,此时就不需要进行接下来的扫描交换了.

    
        /**
         * @description 冒泡排序-1-优化
         * @author zhangdi
         * @param arr
         *            * 针对问题:数据的顺序排好之后,冒泡算法仍然会继续进行下一轮的比较,直到arr.length-1次,后面的比较没有意义的。
         *            方案: 设置标志位flag,如果发生了交换flag设置为true;如果没有交换就设置为false。
         *            这样当一轮比较结束后如果flag仍为false,即:这一轮没有发生交换,说明数据的顺序已经排好,没有必要继续进行下去。
         * 
         */
        public static void BubbleSort1_better(int[] arr) {
    
            int temp;// 临时变量
            boolean flag;
            if (arr == null || arr.length == 0)
                return;
            for (int i = 0; i < arr.length - 1; i++) { // 表示趟数,一共arr.length-1次。
                flag = false;
                for (int j = arr.length - 1; j > i; j--) {
                    if (arr[j] < arr[j - 1]) {
                        temp = arr[j];
                        arr[j] = arr[j - 1];
                        arr[j - 1] = temp;
                    }
                }
                if (!flag)
                    break;
            }
        }
    

    冒泡排序三改进

    上面的算法还有优化的空间吗?答案是有,假如存在一个数组,前缀几个元素是无序的,而后面大部分皆是有序的,上面的版本并不能解决这种情况下出现的中间部分的反复的扫描,这些扫描交换的元素集中在数组前部.
    多出来的时间消耗是后缀中已经有序的元素的反复的扫描交换,其实是不必要的;–>如何确定最后扫描交换的元素的标志在哪?而不是亦步亦趋的逐步收缩.
    由此得出版本三

        /**
         * @description 冒泡排序-3
         * @param arr
         * @author zhangdi
         */
        private static void BubbleSort1_better(int[] array) {
            int tmp = 0;
            // 记录最后一次交换的位置
            int lastExchangeIndex = 0;
            // 无序数列的边界,每次比较只需要比到这里为止
            int sortBorder = array.length - 1;
            for (int i = 0; i < array.length; i++) {
                // 有序标记,每一轮的初始是true
                boolean isSorted = true;
                for (int j = 0; j < sortBorder; j++) {
                    if (array[j] > array[j + 1]) {
                        tmp = array[j];
                        array[j] = array[j + 1];
                        array[j + 1] = tmp;
                        // 有元素交换,所以不是有序,标记变为false
                        isSorted = false;
                        // 把无序数列的边界更新为最后一次交换元素的位置
                        lastExchangeIndex = j;
                    }
                }
                sortBorder = lastExchangeIndex;
                if (isSorted) {
                    break;
                }
            }
        }
  • 相关阅读:
    ASP.NET面试资料【六】
    让Google帮你托管AJAX库
    JavaScript:prototype属性使用说明【转】
    如何存储Session
    给HyperLink控件连接资源文件
    Atcoder Regular Contest 096 D Sweet Alchemy(贪心+多重背包)
    NOI2021 去不了记
    一个测试你的浏览器支持多少HTML5元素的网站
    json怎么读
    QT元件(QTableView、QSql*之类)的最好开在堆空间中用指针操作
  • 原文地址:https://www.cnblogs.com/DiZhang/p/12544977.html
Copyright © 2011-2022 走看看