建议结合画图进行理解
1.挖坑填补法实现快速排序(遇到逆序直接扑街):
void quicksort(int *arr,unsigned int len)(挖坑填补方法实现)
{
if (len<2) return; // 数组的元素小于2个就不用排序了。
int temp=arr[0]; // 选取最左边的数作为基准。
int left=0; // 左下标。
int right=len-1; // 右下标。
int moving=2; // 当前应该移动的下标,1-左下标;2-右下标。
while (left<right)
{
if (moving==2) // 移动右下标的情况。
{
// 如果右下标位置元素的值大于等于中心轴,继续移动右下标。
if (arr[right]>=temp) { right--; continue; }
// 如果右下标位置元素的值小于中心轴,把它填到左下标的坑中。
arr[left]=arr[right];
left++; // 左下标向右移动。
moving=1; // 下次循环将移动左下标。
continue;
}
if (moving==1) // 移动左下标的情况。
{
// 如果左下标位置元素的值小等于中心轴,继续移动左下标。
if (arr[left]<=temp) { left++; continue; }
// 如果左下标位置元素的值大于中心轴,把它填到右下标的坑中。
arr[right]=arr[left];
right--; // 右下标向左移动。
moving=2; // 下次循环将移动右下标。
continue;
}
}
// 如果循环结束,左右下标重合,把中心轴的值填进去。
arr[left]=temp;
quicksort(arr,left); // 对中心轴左边的序列进行排序。
quicksort(arr+left+1,len-left-1); // 对中心轴右边的序列进行排序。
/*对arr进行加减操作,传入相应首元素地址,以及对应的数组长度,
实现相当于将原数组切片再传入的感觉。
递归深度一直到达切片的数组长度为 1 */
}
2.二分交换法(逆序状况仍旧无敌):
void quicksort(int* nums,int l,int r)//应用二分思想
{
int mid=nums[(l+r)/2];//中间数
int i=l,j=r;
while(i<=j){//这里注意要有'='(可结合后面的递归传参进行思考)
while(nums[i]<mid) i++;//查找左半部分比中间数大的数
while(nums[j]>mid) j--;//查找右半部分比中间数小的数
if(i<=j)//如果有一组不满足排序条件(左小右大)的数
{/*交换值:这里注意有一个小坑,
不能用加法或者异或来实现值的交换,
因为当nums[i]和nums[j]指的是同一个变量时(i=j时),
就会出现bug。*/
int temp = nums[j];
nums[j] = nums[i];
nums[i] = temp;
i++;
j--;/*实际上这种交换思想得到的不一定将基准值排好位置,
但是在最后一次执行上面两个循环搜索后,r的右边一定是大于等于基准值的,l的左边一定是小于等于基准值的。
还有就是记住当执行l=r的交换,要过前面两道循环坎,所以若为l=r的情况进行交换那么只有可能是该对应的值就是基准值,
所以此时便相当于将基准值排好了,而后再执行此交换是有利于l和r的正确位置,
相当于无论哪种情况,r都会指向左待排数列的尾部,l则指向右待排数列的首部。*/
}
}
if(l<j) quicksort(nums,l,j);//递归搜索左半部分
if(i<r) quicksort(nums,i,r);//递归搜索右半部分
}
我个人常用的快排:
void quicksort(int* nums,int n)//应用二分思想
{ if (n<2)return;
int l=0,r=n-1;
int mid=nums[(l+r)/2];//中间数
while(l<=r){//这里和下面的'='千万不能省,这是让最后l和r的指向可能性只会有两种可能,要么l和r相邻(r左l右),要么l和r中间隔了一个数(那么这个数肯定是确定好位置的。l右r左)
while(nums[l]<mid) l++;//查找左半部分比中间数大的数
while(nums[r]>mid) r--;//查找右半部分比中间数小的数
if(l<=r)//如果有一组不满足排序条件(左小右大)的数
{/*交换值:这里注意有一个小坑,
不能用加法或者异或来实现值的交换,
因为当nums[i]和nums[j]指的是同一个变量时(i=j时),
就会出现bug。*/
int temp = nums[r];
nums[r] = nums[l];
nums[l] = temp;
l++;
r--;
}
}
quicksort(nums,r+1);//递归搜索左半部分
quicksort(nums+l,n-l);//递归搜索右半部分
//最后这个左右搜索部分元素一定不能重合,或者少包含了一些元素(除非是这一轮已经排好的这一个),就算你的左右搜索部分包含了原本已经确定了位置的元素,也没关系。
}
int* sortArray(int* nums,int numSize,int* returnSize){
*returnSize = numSize;
quicksort(nums,numSize);
return nums;
}