• Java排序算法 [快速排序]


    package cn.com.dom4j.sort;
    
    public class QuickSort {
    
        /**
         快速排序
            在 Java中, 快速排序被用作基本数据类型的排序  (当然, 不只快速排序一种)
            快速排序是实践中的一种快速的排序算法, 在 C++或对 Java基本类型的排序证特别有用.
            它的平均运行时间是 O(N logN), 该算法之所以特别快, 主要是由于非常精炼和高度优化的内部循环.
            它的最坏情形性能为 O(N^2), 但经过稍许努力可是这种情形极难出现.
            通过将快速排序和堆排序结合, 由于堆排序的 O(N logN)最坏情形运行时间, 我们可以对几乎所有的输入都能达到快速排序的快速运行时间
         
         */
        public static <AnyType extends Comparable<? super AnyType>> void quickSort(AnyType[] a) {
            quickSort(a, 0, a.length - 1);
        }
    
        /**
         * 快速排序主例程
         * 
         * @param a 原始数组
         * @param left 起始索引
         * @param right 结束索引
         * @param <AnyType> 实现了 Comparable接口的类或其子类
         */
        private static <AnyType extends Comparable<? super AnyType>> void quickSort(AnyType[] a, int left, int right) {
    
            // 定义数组大小边界, 小于这个值时使用插入排序
            int CUTOFF = 10;
    
            // 数组元素较少的时候, 使用插入排序来获取更快的速度; 元素较多时, 使用快排
            if (left + CUTOFF <= right) {
    
                // 三数中值分割法产生枢纽元
                AnyType pivot = median3(a, left, right);
    
                // i: 比枢纽元小的元素起始索引; j: 大元素的起始索引
                int i = left, j = right - 1;
    
                for ( ; ; ) {
                    // 小元素指针不断向右推进, 直到找到比枢纽元大的元素
                    while (a[++i].compareTo(pivot) < 0) {
    
                    }
                    // 大元素指针向左推进, 遇到比枢纽元小的元素终止
                    while (a[--j].compareTo(pivot) > 0) {
    
                    }
                    // 两个索引未交叉时, 代表大小序列还未分割完成, 交换位置后继续分割
                    // 交叉时代表分割完成
                    if (i < j)
                        swap(a, i, j);
                    else
                        break;
                }
    
                // 分割完成后, 将枢纽元和小元素索引终止处的元素位置互换
                // 此时, 枢纽元左侧都为小元素, 右侧都为大元素 (相对于枢纽元而言)
                swap(a, i, right - 1);
    
                // 对分割后的子序列重复上面操作
                quickSort(a, left, i - 1);
                quickSort(a, i + 1, right);
    
            } else {
                insertionSort(a, left, right);
            }
    
        }
    
        /**
         * 对数组的指定部分使用插入排序
         * @param a 原始数组
         * @param left 起始索引
         * @param right 结束索引
         * @param <AnyType> 实现了 Comparable接口的类型或其子类
         */
        private static <AnyType extends Comparable<? super AnyType>> void insertionSort(AnyType[] a, int left, int right) {
    
            if (right - left == 0 || left < 0 || right > a.length - 1) {
                return;
            }
    
            AnyType tmp;
            int j;
            for (int i = left + 1; i <= right; i++) {
                tmp = a[i];
                for (j = i; j > left && tmp.compareTo(a[j - 1]) < 0; j--) {
                    a[j] = a[j - 1];
                }
                a[j] = tmp;
            }
        }
    
        /**
         三数中值分割法
            使用左端, 右端和中心位置上的三个元素的中值作为枢纽元
         */
        private static <AnyType extends Comparable<? super AnyType>> AnyType median3(AnyType[] a, int left, int right) {
    
            int center = (right - left) / 2;
    
            // 对左中右三个位置的元素位置进行调整
            // 最小的元素被放在最左端, 最大的元素放在最右端, 中间的元素放在中间位置, 中间元素要作为枢纽元
            if (a[center].compareTo(a[left]) < 0) {
                swap(a, left, center);
            }
            if (a[right].compareTo(a[left]) < 0) {
                swap(a, left, right);
            }
            if (a[right].compareTo(a[center]) < 0) {
                swap(a, center, right);
            }
            
            // 将枢纽元和右端倒数第二个元素交换位置, 使枢纽元离开数组, 便于元素比较
            swap(a, center, right - 1);
            
            // 将枢纽元返回
            return a[right - 1];
        }
    
        /**
         * 交换数组中两个元素的位置
         */
        private static <AnyType extends Comparable<? super AnyType>> void swap(AnyType[] arr, int i, int j) {
            if (arr == null || arr.length <= 1 || i == j) {
                return;
            }
    
            AnyType tmp = arr[i];
            arr[i] = arr[j];
            arr[j] = tmp;
        }
    }
    

  • 相关阅读:
    nopcommerce商城系统--源代码结构和架构
    nopcommerce商城系统--如何编写一个插件
    ASP.NET MVC:通过 FileResult 向 浏览器 发送文件
    【js与jquery】电子邮箱、手机号、邮政编码的正则验证
    也用 Log4Net 之走进Log4Net (四)
    也用 Log4Net 之将自定义属性记录到文件中 (三)
    也用 Log4Net 之将日志记录到数据库的后台实现 (二)
    也用 Log4Net 之将日志记录到数据库的配置 (一)
    log4net 将日志写入数据库
    ASP.NET MVC 3 入门级常用设置、技巧和报错
  • 原文地址:https://www.cnblogs.com/bobo132/p/13950370.html
Copyright © 2020-2023  润新知