1. 程式人生 > 實用技巧 >快速排序的幾種寫法

快速排序的幾種寫法

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

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

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

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

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

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

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

最後

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