zoukankan      html  css  js  c++  java
  • 排序算法之快速排序

    快速排序是一个速度非常快的交换排序算法,思路比较简单:从一个待排的数据序列中任取一个数据作为分界值,所有比这个值小的数据放到这个数的左边,比这个值大的数据放到右边,这样经过一次下来,这个序列分成了左右两个序列,左边的数据都比分界值小,右边的数据都比分界值大,然后再对左右两个子序列进行递归。所以,快速排序的关键在于第一趟要做的事情。实现思路如下:

    (1)、选出一个分界值。

    (2)、从左往右选出一个比分界值大的数,记录下标 i。

    (3)、从右往左选出一个比分界值小的数,记录下标 j。

    (4)、如果 i < j 交换两个下标处的元素。

    (5)、最后将分界值与 j 下标的元素交换,这样经过第一趟,就把这组数分成了左右两个序列+分界值,左边的序列比分界值小,右边的比分界值大。

    比如这组数:15、9、23、6、4、37、7、24

    首先15作为分界值,i 从左往右遍历,找到23比15大,记录这个下标 i=2; j 从右往左遍历,找到7小于15,记录这个下标 j=6; 满足条件  i< j , 所以交换这两个数。这组元素变成了:

    15、9、7、6、4、37、23、24 然后 i 继续往右,j 继续往左,又找到了4 和 37 此时 i = 5 , j = 4 . 不满足 i < j ,所以不交换,并且跳出第一趟,并且4和15交换。这组数变成了:4、9、7、61537、23、24,这就是第一趟的结果,然后递归左右两个序列。用Java具体实现如下:

    package test.java.sort.demo;
    
    import test.java.sort.Util.DataWrap;
    
    /**
     * 2017-5-16 Java实现快速排序
     * @author tom
     */
    public class FastSortDemo {
    
        /**
         * 交换数组中下标为i和下标为j的两个数
         * @param data
         * @param i
         * @param j
         */
        private static void swap(DataWrap[] data, int i, int j) {
    
            DataWrap temp = data[i];
            data[i] = data[j];
            data[j] = temp;
        }
    
        public static void fastSort(DataWrap[] data, int start, int end) {
            // 需要排序
            if (start < end) {
                // 以第一个元素作为界点
                DataWrap base = data[start];
                int i = start;
                int j = end + 1;
    
                while (true) {
                    // 如果从左到右找到了比分界点大的值,就跳出当前循环,此时i的值记录了这个数的索引
                    while (i < end && data[++i].compareTo(base) <= 0);
                    // 如果从右往左找到了比分界值小的值,跳出当前循环,此时j的值记录了该数的索引
                    while (j > start && data[--j].compareTo(base) >= 0);
                    //i<j时才需要交换,如果i>=j还没有找到左边比分界值大,右边比分界值小的数,说明已经达到了第一趟的要求
                    if (i < j) {
                        swap(data, i, j);
                    } else {
                        break;
                    }
                }
                //把分解值放到合适的位置,j的位置存放的是最后一个比分界值小的数
                swap(data, start, j);
                //递归左右两个序列,j这个位置是上一趟的分界值,已经放到了适当的位置了,所有不需要再排序
                System.out.println(java.util.Arrays.toString(data));
                fastSort(data, start, j-1);
                fastSort(data, j+1, end);
            }
        }
        
        public static void main(String[] args) {
            DataWrap[] data = { 
                    new DataWrap(19, ""), 
                    new DataWrap(45, ""), 
                    new DataWrap(16, ""), 
                    new DataWrap(21, "*"),
                    new DataWrap(23, ""), 
                    new DataWrap(21, ""),
                    new DataWrap(30, ""),};
            System.out.println("排序之前");
            System.out.println(java.util.Arrays.toString(data));
            System.out.println("开始排序");
            fastSort(data,0,data.length-1);
            System.out.println("排序完成");
            System.out.println(java.util.Arrays.toString(data));
        }
    }
    package test.java.sort.Util;
    
    /**
     * 2017-5-15 定义一个数据包装类
     * @author tom
     */
    public class DataWrap implements Comparable<DataWrap> {
        int data;
        String flag;
    
        public DataWrap(int data, String flag) {
            this.data = data;
            this.flag = flag;
        }
    
        @Override
        public String toString() {
            return data + flag;
        }
    
        // 如果当前data大于dw,返回1;小于和等于返回数值不是1
        @Override
        public int compareTo(DataWrap dw) {
            return this.data > dw.data ? 1 : (this.data == dw.data ? 0 : -1);
        }
    }

    程序运行结果:

    排序之前
    [19, 45, 16, 21*, 23, 21, 30]
    开始排序
    [16, 19, 45, 21*, 23, 21, 30]
    [16, 19, 30, 21*, 23, 21, 45]
    [16, 19, 21, 21*, 23, 30, 45]
    [16, 19, 21, 21*, 23, 30, 45]
    [16, 19, 21, 21*, 23, 30, 45]
    排序完成
    [16, 19, 21, 21*, 23, 30, 45]

    快速排序不是一种稳定的排序算法。

  • 相关阅读:
    【PA2014】【BZOJ3709】Bohater(贪心,排序)
    【POJ1328】Radar Installation(贪心,决策包容)
    【NOIP2002】【Luogu1032】字串变换
    【NOIP2010】【Luogu1199】三国游戏
    【NOIP2009】【Luogu1068】分数线划定
    【NOIP2002】【Luogu1036】选数
    【NOIP2004】【Luogu1085】不高兴的津津
    【NOIP2003】【luogu1042】乒乓球
    【NOIP2012】【Luogu1080】国王游戏(贪心,邻项交换)
    Jzoj4894 SJR的直线
  • 原文地址:https://www.cnblogs.com/hello-daocaoren/p/6875900.html
Copyright © 2011-2022 走看看