算法学习之快速排序(一)

近日在学习算法过程中总处在学了就忘的尴尬状态中,遂利用博客来记录学习心得。今天来和大家分享一下我对快速排序的感悟。

首先,目录如下:

  1. 快速排序的原理
  2. 快速排序的代码实现
  3. 快速排序的分析与感悟
  4. 快速排序的优化

原理:
通过每次设置基准将要排序的数组分成两部分,即大于基准的和小于基准的。再在大于基准的一部分中拿取一个作为基准,与上一步一样,将此部分分为两部分,依次进行……

算法实现:
通过算法的原理,我们来开始敲代码。(以Java为例),一看原理介绍中有绝对多步相同操作。我们容易想到了 循环和递归 ,那到底是用循环可以还是递归可以呢?抑或是两者都行,那哪种更为优越呢?先撇在这个问题,我们先想跳出条件,无论是循环还是递归,都需要一个条件来结束、跳出。我们易想到原理中说的每次分成两部分,哪些数可以有机会分成两部分?当然是此部分长度大于1了,那跳出条件就出来了

//1,找到算法的出口,其中low表示这部分的左下标,high表示这部分的右下标 
if( low >= high) {  
     return;  
} 

然后,我们就要制定基准了,基准的选择便是待会优化算法的基础。现在我们为了方便,将基准选择为a[low],通过基准将一生二。选整上代码

private static void quickSort(int[] a, int low, int high) {  
        //1,找到递归算法的出口  
        if( low >= high) {  
            return;  
        }  
        //2,存下标
        int i = low;  
        int j = high;  
        //3,key 基准 
        int key = a[low];  
        //4,完成一趟排序  
        while(i<j) {  
            //4.1,从右往左找到第一个小于key的数  
            while( i<j && a[j] > key){  
                j--;  
            }  
            // 4.2,从左往右找到第一个大于key的数  
            while( i<j && a[i] <= key) {  
                i++;  
            }  
            //4.3,交换  
            if(i<j) {  
                int p = a[i];  
                a[i] = a[j];  
                a[j] = p;
            }  
        }  
        // 4.4,调整key的位置  
        int p = a[i];  
        a[i] = a[low];  
        a[low] = p;  
        //5,对key左边的数快排  
        quickSort(a, low, i-1 );  
        //6,对key右边的数快排  
        quickSort(a, i+1, high);  
    } 

从两端比较这很容易理解,为什么先从右往左找到第一个小于key的数,而不是先从左往右找到第一个大于key的数,抑或是说两者谁在前都一样?以一个整型数组int a[]= {2,1,4,5,7,6,3}, 为例。第一次排序以2作为基准,要是从右边先的话,找到的第一个小于key的数为1,那左边再找第一个大于key的数时,由于i < j,左边下标 i 停留在 1 ,也就是交换了数字 2 和 1(数组下标 0 和 1) ,这样没问题。要是反过来呢?先从左往右找到第一个大于key的数,找到第一个大于基准的数字为 4 (下标为 2 ),再从右往左找到第一个小于key的数,由于i < j,右边下标 j 停留在 4 ,也就是交换了数字 2 和 4(数组下标 0 和 2) ,第一次遍历结果为:4 1 2 5 7 6 3 ,不满足条件。原因何在呢?因为我们将基准选择为a[low]

附上整体代码:

public class QuickSort {  
    public static void main(String[] args) {  
        int a[] = {2,1,4,5,7,6,3};
        System.out.println(Arrays.toString(a));  
        quickSort(a);  
        System.out.println(Arrays.toString(a));  
    }  

    public static void quickSort(int[] a) {  
        if(a.length>0) {  
            quickSort(a,0,a.length-1);  
        }  
    }  

    private static void quickSort(int[] a, int low, int high) {  
        //1,找到递归算法的出口  
        if( low >= high) {  
            return;  
        }  
        //2,存下标
        int i = low;  
        int j = high;  
        //3,key 基准 
        int key = a[low];  
        //4,完成一趟排序  
        while(i<j) {  
            //4.1,从右往左找到第一个小于key的数  
            while( i<j && a[j] > key){  
                j--;  
            }  
            // 4.2,从左往右找到第一个大于key的数  
            while( i<j && a[i] <= key) {  
                i++;  
            }  
            //4.3,交换  
            if(i<j) {  
                int p = a[i];  
                a[i] = a[j];  
                a[j] = p;
            }  
        }  
        // 4.4,调整key的位置  
        int p = a[i];  
        a[i] = a[low];  
        a[low] = p;  
        //5,对key左边的数快排  
        quickSort(a, low, i-1 );  
        //6,对key右边的数快排  
        quickSort(a, i+1, high);  
    }  
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

VERMAN_S

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值