快速排序是非常重要排序算法
有許多寫法,不同寫法在數量級較小的情況下有不同的性能
這里的標兵都是取頭 如果需要隨機化應該加入 如下幾行
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 |
從數據中可以得到 在數量較少的情況下
雙指針交換最耗時間 原因浪費在交換函數的進棧出棧並且邏輯有比較復雜的比較
優化填坑和單指針交換和填坑 效果差不多
最后
理解和記憶簡單取決於自己的選擇