1.算法思想:分治法
时间复杂度:最好:O(nlog2n) 最坏:O(n^2) 但几乎不会达到
2.算法步骤:
(1)先确定分界点,某一个值
(2)调整区间使得≤x的数都在x左边,≥x的数都在x右边
(3)递归左右两边
3.算法流程:
利用双指针循环法
定义两个指针i, j在数组两端,假定一个枢轴量x(数组中某一个数), 如果arr[i]<x,则i++,直到遇见比x大的数停下;如果arr[j]>x,则j--, 直到遇见比x小的数停下
找到那个最终的分界点 在分界点左右两侧进行递归
4.板子:
(1)分隔法版本:终止条件为相等
static int partition(int []arr,int l,int r)
{
int pivot=arr[l],i=l,j=r;
while(i! =j) //约定i,j重合的时候停止
{
while(i<j&&arr[j]>pivot) j--; //有可能j停住i越过j/i停住j越过i
while(i<j&&arr[i]<=pivot) i++; //因此必须用i<j控制重合
if(i<j) //i,j都走不了时,交换二者
{
int temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
}
arr[(l+r)/2]=arr[i]; //把枢轴量放到重合点,保证快排的规则
arr[i]=pivot; //因为终止条件为重合,返回i/j都可
return i;
}
static void quickSort(int []arr,int l,int r) //分界点左右两边递归
{
if(l>=r) return;
int pi=partition(arr,l,r);
quickSort(arr,l,pi-1); //分界点两边进行递归
quickSort(arr,pi+1,r);
}
(2)算法课版本:终止条件为大于等于
static void quickSort(int[] arr, int l, int r)
{
if (l >= r) return;
int i = l - 1, j = r + 1, pivot = arr[(l+r)/2];
//i,j偏移一位,为了后面do-while的指针移动
//枢轴量设置两端、中间值均可(最好是中间值,以防两端出现边界问题,即正序、逆序时可能出现无限划分的问题,导致超时)
while (i < j)//终止条件为i>=j
{
do i++; while (arr[i] < pivot); //先走再判断,恰好照应指针初始取值
do j--; while (arr[j] > pivot);
if (i < j) //i,j都走投无路时 交换值接着走
{
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
//因为终止条件是i>=j,也就是i,j可以重合时终止(恰为pivot时),这时候分界点取i/j都可;也可以j<i时停止,这时候分界点就要取j,因为i停下说明遇到了大数,j则遇到了小数,所以j及其左侧都是小于pivot的,j+1右侧就都是大于pivot的 综上分界点应该取j或者i-1(最终一定是j在i左侧紧挨着i)
quickSort(arr, l, j);
quickSort(arr, j + 1, r);
}
→代码解释含在代码里,可以结合理解