zoukankan      html  css  js  c++  java
  • 排序---快速排序及其切分函数Partition应用

    快速排序

      快速排序通过一个切分元素将数组分成两个子数组,左子数组小于等于切分元素,右子数组大于切分元素,将这两个子数组排序,也就是将整个数组排序了。

    代码如下:

    public class Sort{
        public static void quickSort(int []arr){
            if(arr=null||arr.length<2)
                return;
            quickSort(arr,0,arr.length-1);
        }
        public static void quickSort(int[]arr,int l,int r){
            if(l<r){
                swap(arr, l + (int) (Math.random() * (r - l + 1)), r); //随机选取切分值,然后交换到数组最后一位
                int []p=partition(arr,l,r);//返回于切分值相等的左右界
                quickSort(arr,l,p[0]-1);
                quickSort(arr,p[1]+1,r);
            }
        }
        public static int[]partition(int[]arr,int l,int r){
            int less=l-1; //小于区域的右边界
            int more=r;   //大于区域的左边界,初始包含最右端元素,即切分值。
            while(l<more){
                if(arr[l]<arr[r]){ //arr[r]作为切分值
                    swap(arr,++less,l++); //如果当前元素小于切分值,那么将当前元素和小于区域的右边第一个元素和当前元素交换,小于区域向右扩大一位,访问下一个元素,继续进行比较。
                }else if(arr[l]>arr[r]){
                    swap(arr,--more,l);//如果当前元素大于切分值,那么将当前元素和大于区域的左边第一个元素和当前元素交换,大于区域向左扩大一位,继续访问当前元素,进行比较。
                }else{ //和切分值相等
                    l++;
                }
            }
            swap(arr,more,r); //将切分值换到中间
            return new int[]{less+1,more}; //与切分值相等的区间
        }
        public static void swap(int[]arr,int more,int r){
            arr[more]=arr[more]^arr[r];
            arr[r]=arr[more]^arr[r];
            arr[more]=arr[more]^arr[r];
        }
    }
    

      快速排序是原地排序,不需要辅助数组,但是递归调用需要辅助栈。快速排序最好的情况下是每次都正好将数组对半分,这样递归调用次数才是最小的。这种情况下比较次数为Cn=2Cn/2+n,复杂度为O(NlogN)。

      最坏的情况是,第一次从最大的元素或最小的元素切分,第二次从第二大或者第二小的元素切分,如此这般,最坏情况下的比较次数为N * N /2。为了防止数组一开始就是有序的,我们在选择切分值是,进行随机选取。

      切分函数partition的应用,荷兰国旗问题,将数组分成三部分,分别对应于小于,等于,大于 切分元素。时间复杂度为O(n)。

    public int[]partition(int []arr,int l,int r){
         int less=l-1; //小于区域的右边界
            int more=r;   //大于区域的左边界,初始包含最右端元素,即切分值。
            while(l<more){
                if(arr[l]<arr[r]){ //arr[r]作为切分值
                    swap(arr,++less,l++); //如果当前元素小于切分值,那么将当前元素和小于区域的右边第一个元素和当前元素交换,小于区域向右扩大一位,访问下一个元素,继续进行比较。
                }else if(arr[l]>arr[r]){
                    swap(arr,--more,l);//如果当前元素大于切分值,那么将当前元素和大于区域的左边第一个元素和当前元素交换,大于区域向左扩大一位,继续访问当前元素,进行比较。
                }else{ //和切分值相等
                    l++;
                }
            }
            swap(arr,more,r); //将切分值换到中间
            return new int[]{less+1,more}; //与切分值相等的区间
    }
    
  • 相关阅读:
    eclipse.ini
    Windows8.1硬盘安装Ubuntu14.04双系统参考教程和多硬盘的注意事项[画画]
    【HTML+CSS】(1)基本语法
    Apache Curator获得真正的
    LVM逻辑卷管理@设备、格式、摩、引导自己主动安装一个完整的章节
    这么多的技术,作为一个freshman,什么研究?
    【JUnit4.10来源分析】0导航
    难度0 大写和小写交换
    java06
    java05
  • 原文地址:https://www.cnblogs.com/yjxyy/p/11103372.html
Copyright © 2011-2022 走看看