Java实现快速排序 及详解

13 篇文章 0 订阅

快速排序

概述

快速排序(Quicksort)是对冒泡排序的一种改进。

快速排序由C. A. R. Hoare在1960年提出。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列

简而言之,快速排序就是,先确定一个中间值,这个值通常是 第一个数字,然后将所有比它小的值放到它前面,这样,以它为中线,左右又分为不同的两组,在左右两组循环以上操作,即可完成排序。
在这里插入图片描述
图源:百度百科

原理

一趟快速排序的算法是:

1)设置两个变量i、j,开始的时候:i=0,j=N-1,需要排序的数组为 int[ ] A;

2)以第一个数组元素作为关键数据,赋值给key,即key=A[0];

3)从j开始向前搜索,即由后开始向前搜索(j–),找到第一个小于key的值A[j],将A[j]和A[i]的值交换;

4)从i开始向后搜索,即由前开始向后搜索(i++),找到第一个大于key的A[i],将A[i]和A[j]的值交换;

5)重复第3、4步,直到i=j; (3,4步中,没找到符合条件的值,即3中A[j]不小于key,4中A[i]不大于key的时候改变j、i的值,使得j=j-1,i=i+1,直至找到为止。找到符合条件的值,进行交换的时候i, j指针位置不变。另外,i==j这一过程一定正好是i+或j-完成的时候,此时令循环结束)。

排序演示

假设一开始序列{xi}是:5,3,7,6,4,1,0,2,9,10,8。

此时,ref=5,i=1,j=11,从后往前找,第一个比5小的数是x8=2,因此序列为:2,3,7,6,4,1,0,5,9,10,8。

此时i=1,j=8,从前往后找,第一个比5大的数是x3=7,因此序列为:2,3,5,6,4,1,0,7,9,10,8。

此时,i=3,j=8,从第8位往前找,第一个比5小的数是x7=0,因此:2,3,0,6,4,1,5,7,9,10,8。

此时,i=3,j=7,从第3位往后找,第一个比5大的数是x4=6,因此:2,3,0,5,4,1,6,7,9,10,8。

此时,i=4,j=7,从第7位往前找,第一个比5小的数是x6=1,因此:2,3,0,1,4,5,6,7,9,10,8。

此时,i=4,j=6,从第4位往后找,直到第6位才有比5大的数,这时,i=j=6,ref成为一条分界线,它之前的数都比它小,之后的数都比它大,对于前后两部分数,循环以上方法排序即可。

代码

package sort;

public class QuickSort {
    public static void main(String[] args) {
//        int[] array = {49, 38, 65, 97, 76, 13, 27, 49};
//        int i = 0;
//        int j = array.length-1;
//        int[] ints = quickSort(array, i, j);
//        for (int anInt : ints) {
//            System.out.print(anInt + " ");
//        }
        int[] array = new int[80000];
        for (int i = 0; i < array.length; i++) {
            array[i] = (int)(Math.random()*800000);
        }
        int i = 0;
        int j = array.length-1;
        long startTime=System.currentTimeMillis();
        quickSort(array, i, j);
        long endTime=System.currentTimeMillis();
        System.out.println("程序运行时间: "+(endTime - startTime)+"ms");
    }
    //快速排序排序80k长度的数组,在我这台电脑上只用了0.05秒左右,而希尔排序则需要0.09秒多
    public static int[] quickSort(int[] array, int start, int end){
        int i = start;
        int j = end;//保存本次开始和结束的下标,方便对其操作而不改变其原数据大小
        int key = array[i];//中间值通常为开始的那个数字
        while (i < j){
            //从后向前找,只要没找到比中间值小的数字,就继续往前找
            while (i < j && array[j] >= key ){
                j--;
            }
            //找到后退出循环,交换以j和i为下标数字的位置
            int temp = array[j];
            array[j] = array[i];
            array[i] = temp;
            //交换完,再从前向后找,直到找到比中间值大的数字,退出循环
            while (i < j && array[i] <= key){
                i++;
            }
            //找到后交换i,j的位置
            temp = array[j];
            array[j] = array[i];
            array[i] = temp;
        }
        //↑结束循环,此时中间值前的数字全部小于中间值,后面的数字全部大于中间值
        //判断,防止需要排序的只剩一个数字了还继续递归
        if (i-1>start) {
            //递归,对中间值前面的部分排序
            array=qsort(array,start,i-1);
        }
        if (j+1<end) {
            //递归,对中间值后面的部分排序
            array=qsort(array,j+1,end);
        }
        return array;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值