快速排序--基准定位,分而治之

快速排序的思想
快速是这个算法的特点,所以为了效率出现频度也会很高。快速排序:基准元素+二分思想,分治的标准是相比于基准元素值的大小(比如相比于基准元素大的放右边,小的放左边),分治思想的执行提高了执行效率。

快速排序代码

public class QuickSort {//快速排序的递归排序

    public static void main (String args[]){
        //初始化要排序的数组
        int[] sum={2,7,99,55,2,21};
        //实现排序的方法
        quickSort(sum,0,sum.length-1);
        //循环输出
        for (int i: sum){
             System.out.print(i+" ");
        }
    }

    /**
     * 分治方法的递归实现
     * @param attr 需要排序的数组
     * @param left 最左边元素下标
     * @param right 最右边元素下标
     */
    public static void quickSort(int []attr, int left, int right){
         //如果左边元素下标大于等于右边元素下标,即时同一元素,则结束递归
         if (left>=right)
          return;
         //获得定位元素的位置,也就是左右分界线元素的下标
         int q = partition(attr, left, right);
         //左边部分递归实现,范围为[left,q-1]
         quickSort(attr, left, q-1);
         //右边部分递归实现,范围为[q+1,right]
         quickSort(attr, q+1, right);
        }

    /**
     * 归位基本元素,返回划分元素的位置
     * @param attr 划分的数组
     * @param left 最左元素下标
     * @param right 最右元素下标
     * @return  返回归位的位置
     */
    public static int partition(int []attr, int left, int right){
        //基准元素,要归位的元素
        int sign = attr[left];
        //要排序序列最左元素下标
        int i = left;
        //要排序序列的最右元素的下标加1,因为下边循环我们是--操作
        int j = right+1;
        //置换中间变量
        int temp;
        //如果待比较元素数目大于2则继续比较
        while (i < j){
            //基准元的素下一元素小于基准元素  并且  基准元素位置小于要排序的元素数目  则继续(++操作找到比基准元素大的那个元素)
            while (attr[++i] < sign && i< right);
            //要排序的数组最后一位元素的值大于基准元素则继续(--操作找到比基准元素小的元素为止)
            while(attr[--j] > sign);
            //如果位置正确,置换上边寻找到的两个元素
            if (i < j){
                temp = attr[i];
                attr[i] = attr[j];
                attr[j] = temp;
            }
        }
        //待比较元素不大于2,即两元素比较的位置相遇了,置换基准元素到相遇的位置,完成归位
        attr[left] = attr[j];
        attr[j] = sign;
        //返回归位的位置
        return j;
    }
}

快速排序的时间复杂度
1.快速排序每次将待排序数组二分为两个部分,在理想状况下,每一次都将待排序数组划分成等长两个部分,则需要logn次划分。
2.在最坏情况下,即数组已经有序或大致有序的情况下,每次划分只能减少一个元素,快速排序将不幸退化为冒泡排序,所以快速排序时间复杂度下界为O(nlogn),最坏情况为O(n^2)。
3.在实际应用中,快速排序的平均时间复杂度为O(nlogn)。优于冒泡排序,在各大算法中算是时间较小的。

快速排序的稳定性
在基准元素和a[j]交换的时候,很有可能把前面的元素的稳定性打乱,比如序列5 3 3 4 3 8 9 10 11,现在中枢元素5和3(第5个元素,下标从1开始计)交换就会把元素3的稳定性打乱,所以快速排序是一个不稳定的排序算法。

总结
可以看到,快速排序的代码量与冒泡排序相比,庞大了不少,思路就是不断的实现二分和归位目标元素,来完成整个排序算法,递归的使用让我们不必再担心循环的次数了。



快速排序升级版–挖坑排序

挖坑排序
挖坑排序也算是快速排序,相比快速排序,代码量缩减很多。挖坑排序的思想也是分治+递归+基准元素归位实现的,但是挖坑是顺序填补元素的,也就是目标元素顺序填补从所给数据倒序符合的元素,反过来同理倒序填补所给元素顺序查找符合的元素。可以看到代码量也是比较简短的。

挖坑排序代码

public class Quick {

    public static void main(String[] args) {
        //初始化要排序的数组
        int[] sum={2,7,99,55,2,21};
        //实现排序的方法
        quick_sort(sum,0,sum.length-1);
        //循环输出
        for (int i: sum){
            System.out.print(i+" ");
        }
    }

    /**
     * @param s 目标数组
     * @param l 要排序数组最左元素下标
     * @param r 要排序数组最右元素下标
     */
    static void quick_sort(int attr[], int l, int r){  
        if (l < r){  
            int i = l; 
            int j = r;
            int sign = attr[l];  //要归位的元素
            while (i < j){  
                while(i < j && attr[j] >= sign) // 从右向左找第一个小于基准数sign的数  
                    j--;    
                if(i < j)   
                    attr[i++] = attr[j];  //顺序填补倒序查找到的元素

                while(i < j && attr[i] < sign) // 从左向右找第一个大于等于基准数sign的数  
                    i++;    
                if(i < j)   
                    attr[j--] = attr[i];  //倒序填补顺序查找到的元素
            }  
            //基准元素归位
            attr[i] = sign;  
            quick_sort(attr, l, i - 1); // 递归调用   
            quick_sort(attr, i + 1, r);  
        }  
    }  

}

详细图文介绍请参考大神博文:http://www.cnblogs.com/morewindows/archive/2011/08/13/2137415.html

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值