快速排序复习

Posted 小智RE0

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了快速排序复习相关的知识,希望对你有一定的参考价值。

基本思想;类似于归并排序的分治思想,
但是 在快速排序中会将数组中的元素 小的放一边,大的放一边;排序即完成;

找切分点,假设数组的第一个元素作为切分点,然后和后面的元素进行比较,
只要比当前这个切分点元素小的,就向前交换, 直到数组末尾;再将切分点放到它的指针指向的合适位置;
此时得到一个基于切分点分开的两块区域, 左侧元素普遍小于切分点元素值;右侧元素普遍大于切分点元素值;

此时按照第一个切分,逐次向左向右进行递归;最终在一个一个切分点的作用下,其实就完成了排序;

912. 排序数组题目中测试

class Solution 
    public int[] sortArray(int[] nums) 
        int n = nums.length;
        if(n < 2) return nums;
        quickSort(nums,0,n-1);
        return  nums;
    

    private void quickSort(int[] nums,int left,int right)
        //递归结束条件;
        if(right - left <= 7)
            //使用插入排序;
            useInsertSort(nums,left,right);
            return;
        

        //找到合适的分隔点;
        int segIndex = getSegIndex(nums,left,right);
        //递归;
        quickSort(nums,left,segIndex - 1);
        quickSort(nums,segIndex+1, right);
    

    //使用分隔点将左右两边的元素 完成一轮区分;
    private int getSegIndex(int[] nums,int left,int right)
        //一般用首节点;
        int segVal = nums[left];
        //指针j,用来在比较时的元素交换;
        int j = left;
        for(int i = left+1;i<=right;i++)
            //仅将小元素向前换;
            if(segVal > nums[i])
                j++;
                swap(nums,i,j);
            
        
        //最后将首节点的元素放到合适的位置;
        swap(nums,left,j);
        return j;
    

    //插入排序;
    private void useInsertSort(int[] nums,int left,int right)
        //插入排序由第2个元素开始;
        for(int i=left+1;i<=right;i++)
            //使用临时变量;
            int temp = nums[i];
            int j = i;
            for(;j>left;j--)
                if(nums[j-1]>temp)
                    nums[j] = nums[j-1];
                else
                    break;
                
            
            nums[j] = temp;
        
    

    //交换元素;
    private void swap(int[] nums,int a,int b)
        int temp = nums[a];
        nums[a] = nums[b];
        nums[b] = temp;
    

优化;如果一直用数组的头一个元素作为切分点时,可能出现某些测试用例的特殊情况,影响执行效率;
那么可以每次找一个随机的节点作为切分点;

class Solution 
    public int[] sortArray(int[] nums) 
        int n = nums.length;
        if(n < 2) return nums;
        quickSort(nums,0,n-1);
        return  nums;
    

    private void quickSort(int[] nums,int left,int right)
        //递归结束条件;
        if(right - left <= 7)
            //使用插入排序;
            useInsertSort(nums,left,right);
            return;
        

        //找到合适的分隔点;
        int segIndex = getSegIndex(nums,left,right);
        //递归;
        quickSort(nums,left,segIndex - 1);
        quickSort(nums,segIndex+1, right);
    

    //使用一个规定的随机数对象;
    private final Random R = new Random();
    //使用分隔点将左右两边的元素 完成一轮区分;
    private int getSegIndex(int[] nums,int left,int right)
        //找一个随机的节点作为切分点;
        int ran =left + R.nextInt(right - left +1);
        swap(nums,left,ran);
        //这里的切分点实际就是交换后的随机节点的值;
        int segVal = nums[left];
        //指针j,用来在比较时的元素交换;
        int j = left;
        for(int i = left+1;i<=right;i++)
            //仅将小元素向前换;
            if(segVal > nums[i])
                j++;
                swap(nums,i,j);
            
        
        //最后将首节点的元素放到合适的位置;
        swap(nums,left,j);
        return j;
    

    //插入排序;
    private void useInsertSort(int[] nums,int left,int right)
        //插入排序由第2个元素开始;
        for(int i=left+1;i<=right;i++)
            //使用临时变量;
            int temp = nums[i];
            int j = i;
            for(;j>left;j--)
                if(nums[j-1]>temp)
                    nums[j] = nums[j-1];
                else
                    break;
                
            
            nums[j] = temp;
        
    

    //交换元素;
    private void swap(int[] nums,int a,int b)
        int temp = nums[a];
        nums[a] = nums[b];
        nums[b] = temp;
    

用时直接缩减好多;


之前学习的双指针法快排,在这道题中运算,效率不太行;
学习数据结构笔记(6)====>八大排序算法(Sort Algorithm)[冒泡,选择,插入,快速,希尔,基数,归并,堆排序]

class Solution 
    public int[] sortArray(int[] nums) 
        int n = nums.length;
        if(n < 2) return nums;
        //定义临时数组;
        return quickSort(nums,0,n-1); 
    

     /**
     * 快速排序
     * @param array 需要排序的数组
     * @param left  左指针
     * @param right 右指针
     * @return      排序后的数组
     */
    public static int[] quickSort(int[] array,int left,int right)
        //先把左右指针提前存起来;
        int l = left;
        int r = right;
        //找到中心点;
        int bottom = array[(left +right)/2];
        System.out.println("当前中心轴值-->"+bottom);
        //左指针 和 右指针向中心移动;
        while (l < r)
            //左右指针移动;
            while (array[l] < bottom)
                l+=1;
            
            while (array[r] > bottom)
                r-=1;
            

            //跳出循环的条件;
            if(l>=r)
                break;
            
            //先进行交换;
            int temp =array[l];
            array[l] = array[r];
            array[r] = temp;

            //考虑接近到达中心点的情况;
            if(array[l] == bottom)
                r-=1;
            
            if(array[r] == bottom)
                l+=1;
            
        

        //还需考虑两指针相遇的情况;
        if(l == r)
            l+=1;
            r-=1;
        

        //向左递归;
        if(left<r)
            quickSort(array,left,r);
        

        //向右递归;
        if(right>l)
            quickSort(array,l,right);
        

        return array;
    


以上是关于快速排序复习的主要内容,如果未能解决你的问题,请参考以下文章

快速排序复习

java十年技术栈[总结复习用]

为啥我的基数排序 JAVA 实现比快速排序慢?

快速排序

为啥我的基数排序 python 实现比快速排序慢?

基数排序时间