快速排序的幾種寫法


快速排序是非常重要排序算法

有許多寫法,不同寫法在數量級較小的情況下有不同的性能

這里的標兵都是取頭 如果需要隨機化應該加入 如下幾行

int randomindex=l+1+random.nextInt(r-l);
int temp = nums[l];
nums[l]=nums[randomindex];
nums[randomindex]=temp;

No.1 填坑

取走標兵 ,從數組尾開始填充數組頭的空缺

有相對復雜的比較

 public static void partition1(int[] nums,int l,int r){
        if(l<r){
            int pivot = nums[l];
            int i=l,j=r;
            while(i<j){
                while (i<j && nums[j]>=pivot){
                    j--;
                }
                nums[i]=nums[j];
                while (i<j && nums[i]<=pivot){
                    i++;
                }
                nums[j]=nums[i];
            }
            nums[i]=pivot;
            partition1(nums,l,i-1);
            partition1(nums,i+1,r);
        }
        return;
 }

No.2 雙指針交換

和填坑不同的是 直接交換

有浪費時間的函數交換

public static void partition2(int[] nums,int l,int r){
    if(l<r){
        int pivot=nums[l];
        int i=l,j=r;
        while(i<j){
            while (i<j && nums[j]>=pivot){
                j--;
            }
            while (i<j && nums[i]<=pivot){
                i++;
            }
            swap(nums,i,j);
        }
        swap(nums,i,l);
        partition2(nums,l,i-1);
        partition2(nums,i+1,r);
    }
}
public static void swap(int[] nums,int i,int j){
    int temp=nums[i];
    nums[i]=nums[j];
    nums[j]=temp;
}

No.3 單指針交換

單指針交換是代碼量最少的

這里的單指針意思是定了一個,而動另一個

較少的比較和交換

public static void swap(int[] nums,int i,int j){
    int temp=nums[i];
    nums[i]=nums[j];
    nums[j]=temp;
}
public static void partition3(int[] nums,int l,int r){
    if(l<r){
        int pivot = nums[l];
        int index=l;
        for(int i=l+1;i<=r;i++){
            if(nums[i]<pivot) {
                ++index;
                swap(nums, i, index);
            }
        }
        swap(nums,l,index);
        partition3(nums,l,index-1);
        partition3(nums,index+1,r);
    }
}

No.4 優化填坑

優化填坑相比於填坑 ,減少了比較次數 指針移動更加快了

沒有交換 ,減少了比較

public static void partition4(int[] nums,int l,int r){
        if(l<r){
            int i=l,j=r,pivort;
            pivort=nums[l];
            while(i<j){
                while (i<j && nums[j]>=pivort){
                    j--;
                }
                if(i<j){
                    nums[i++]=nums[j];
                }
                while (i<j && nums[i]<=pivort){
                    i++;
                }
                if(i<j){
                    nums[j--]=nums[i];
                }
            }
            nums[i]=pivort;
            partition4(nums,i+1,r);
            partition4(nums,l,i-1);
        }
    }

效率對比

用5次相同的隨機數組測試平均值如下

數量級 數字范圍 優化填坑 填坑 雙指針交換 單指針交換
100 0-100 22300.0 25960.0 28020.0 32480.0
100數量級排行 1 2 3 4
1000 0-1000 158220.0 149360.0 188280.0 155400.0
1000數量級排行 3 1 4 2
10000 0-10000 1112180.0 1607860.0 1629740.0 1133740.0
10000數量級排行 1 3 4 2
100000之后差不多水平 On 限制
綜合排行 1 2 4 3

從數據中可以得到 在數量較少的情況下

雙指針交換最耗時間 原因浪費在交換函數的進棧出棧並且邏輯有比較復雜的比較

優化填坑和單指針交換和填坑 效果差不多

最后

理解和記憶簡單取決於自己的選擇


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM