首页 > 代码库 > 排序算法之快速排序

排序算法之快速排序

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

(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 =http://www.mamicode.com/ 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 =http://www.mamicode.com/= 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]

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

排序算法之快速排序