1.数组中的元素为0或1时返回
2.选取枢纽元素pivot
3.将数组S分成两个不相交的集合。切分:大于pivot的元素在左边,小于pivot的元素在右边。
4.对[lo, pivot - 1] 区间内的数组排序,排序pivot,排序[pivot + 1,hi]数组。
收益:类似归并排序,只不过快速排序是先切分,再递归;而归并排序则是向递归,在合并。
inline static void
swap(int *a, int *b)
{
//不能使用异或交换值,*a和*b相同时,异或结果为0
int tmp = *a;
*a = *b;
*b = tmp;
}
//version1
int partition(int nums[], int lo, int hi)
{
swap(nums[lo], nums[(lo + hi) / 2]);
int i, j;
int pivot = nums[lo];
i = lo, j = hi + 1;
while (true)
{
while (nums[++i] < pivot) {}
while (nums[--j] > pivot) {}
if (i < j)
swap(&nums[i], &nums[j]);
else
break;
}
swap(&nums[j], &nums[lo]);
return j;
}
void quiksort(int nums[], int lo, int hi)
{
if (hi <= lo)
return ;
int piv = partition(nums, lo, hi);
quiksort(nums, lo, piv - 1);
quiksort(nums, piv + 1, hi);
}
//version2:三数中值分割法。
void InsertionSort(int nums[], int lo, int hi)
{
int i = lo + 1;
int j = lo;
int tmp;
for (;i <= hi; ++i)
{
tmp = nums[i];
j = i - 1;
if (tmp < nums[j])
{
while ( lo <= j && tmp < nums[j])
nums[j + 1] = nums[j--];
nums[j] = tmp;
}
}
}
/*
**对nums[lo],nums[mid],nums[hi]进行排序。
**把最小元素放在最左边,最大元素放在最右边,枢纽元放在hi-1上
*/
int median3(int nums[], int lo, int hi)
{
int center = lo + (hi - lo)/2;
//比较左边
if (nums[lo] > nums[center])
swap(&nums[lo], &nums[center]);
if (nums[lo] > nums[hi])
swap(&nums[lo], &nums[hi]);
if (nums[center] > nums[hi])
swap(&nums[center], &nums[hi]);
swap(&nums[center], &nums[hi - 1]);
return nums[hi - 1];
}
int partition(int nums[], int lo, int hi)
{
int i, j;
int pivot;
pivot = median3(nums, lo, hi);
i = lo; j = hi - 1;
while (i < j)
{
//i指向一个大于pivot的元素, j指向一个小于pivot的元素
while (nums[++i] < pivot) {}
while (nums[--j] > pivot) {}
if (i < j) // i 不小于 j 时,nums[i]大于pivot;nums[j] 小于 pivot
swap(&nums[i], &nums[j]);
else
break;
}
//交换的nums[i],这是因为pivot放在最右边
//右的是大于pivot的,所以用i
swap(&nums[i], &nums[hi - 1]);
return i;
}
void quiksort(int nums[], int lo, int hi)
{
if (lo + 3 <= hi)
{
int piv = partition(nums, lo, hi);
quiksort(nums, lo, piv - 1);
quiksort(nums, piv + 1, hi);
}
else
InsertionSort(nums, lo, hi);
}
//version3
void quiksort(int nums[], int lo, int hi)
{
if (hi <= lo)
return ;
swap(&nums[lo], &nums[(lo + (hi - lo) / 2)]);
int i = lo, j = hi;
int pivot = nums[lo];
while (i < j)
{
//需先从左边开始
while (j >= lo && nums[j] > pivot) ++i;
if (i < j)
nums[i++] = nums[j];
while (i <= hi && nums[i] < pivot) --j;
if (i < j)
nums[j--] = nums[i];
}
s[j] = pivot;
quiksort(nums, lo, j - 1);
quiksort(nums, j + 1, hi);
}