快速排序是非常重要排序算法
有许多写法,不同写法在数量级较小的情况下有不同的性能
这里的标兵都是取头 如果需要随机化应该加入 如下几行
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 |
从数据中可以得到 在数量较少的情况下
双指针交换最耗时间 原因浪费在交换函数的进栈出栈并且逻辑有比较复杂的比较
优化填坑和单指针交换和填坑 效果差不多
最后
理解和记忆简单取决于自己的选择