学过数据结构的小伙伴都知道,快速排序与冒泡排序都是交换排序,且相较于冒泡排序,快速排序应用更广,程序也相对复杂。其平均时间复杂度在O(n*logn),与希尔排序,归并排序,堆排序等“同台竞争”。但在序列有序的情况下,其时间复杂度会退化到O(n^2),甚至比不上冒泡排序。我们先来看看快速排序的代码。
void swap(int* a1, int* a2)
{
int t = *a1;
*a1 = *a2;
*a2 = t;
}
void Qsort(int* arr, int left, int right)
{
if (left >= right)
{
return;
}//只有一个元素或区域不存在时返回
//int midi = Getmid(arr, left, right);
//swap(&arr[left],&arr[midi]);
int key = left;
int begin = left;
int end = right;
while (begin < end)
{
while (begin<end && arr[end]>=arr[key])
{
end--;
}
while (begin < end && arr[begin] <= arr[key])
{
begin++;
}
swap(&arr[begin], &arr[end]);
}
swap(&arr[key], &arr[begin]);
Qsort(arr,left,begin-1);
Qsort(arr, end+1, right);
}
实现的主要逻辑是递归,采取的是一种分而治之的理念。打个比方,一个数组如果在理想的条件下,快速排序每次取出数组中元素的·一半,分出来的层次少。而在有序的情况下,快速排序每次只能拿出1个元素,层次较多。为解决这个问题,我们采用“三数取中”的方式,将最左边,最右边和中间的元素进行比较。将三个数中中间大小的元素当作“轴”,就避免了有序。具体代码如下。
void swap(int* a1, int* a2)
{
int t = *a1;
*a1 = *a2;
*a2 = t;
}
void Qsort(int* arr, int left, int right)
{
if (left >= right)
{
return;
}//只有一个元素或区域不存在时返回
int midi = Getmid(arr, left, right);
swap(&arr[left],&arr[midi]);
int key = left;
int begin = left;
int end = right;
while (begin < end)
{
while (begin<end && arr[end]>=arr[key])
{
end--;
}
while (begin < end && arr[begin] <= arr[key])
{
begin++;
}
swap(&arr[begin], &arr[end]);
}
swap(&arr[key], &arr[begin]);
Qsort(arr,left,begin-1);
Qsort(arr, end+1, right);
}
int Getmid(int* a, int left,int right)
{
int midi = (left + right) / 2;
if (a[left]< a[midi])
{
if (a[right] < a[left])
{
return left;
}
else if (a[midi] < a[right])
{
return midi;
}
else
return right;
}
else//a[left]>=a[midi]
{
if (a[midi] > a[right])
{
return midi;
}
else if (a[left] < a[right])
{
return left;
}
else
return right;
}
}