快速排序是一种非常高效的排序算法,原理为:对于一组给定的数据,取一个基准值,把小于基准值的数放到前部分,大于基准值的放到后部分,其中前部分的所有数都不大于后部分任意一个数,然后再依次对前后两部分的数进行快排,递归该过程,直到序列中的所有数均为有序为止。
以数组{4,6,3,1,2,7,8,9,5}为例:
第一步:以4为基准值,[2,1,3] 4 [6,7,8,9,5]
第二步:分别以2,6为基准值,[1] 2 [3] 4 [5] 6 [7,8,9]
第三步:以7为基准值,1,2,3,4,5,6,7,[8,9]
第四步:以8为基准值,1,2,3,4,5,6,7,8,9
平均时间复杂度为O(nlogn),平均空间复杂度O(logn)
1.
//快速排序
#include<stdio.h>
void Sort(int a[], int low, int high)
{
if (low >= high)
return;
int i = low;
int j = high;
//取a[i]为基准关键字
int index = a[i];
//把小于index的数分到前面,大于Index的数分到后面
while (i < j)
{
while (i<j && a[j] > index)
--j;
if (i < j)
a[i++] = a[j];
while (i < j && a[i] < index)
++i;
if (i < j)
a[j--] = a[i];
}
a[i] = index;
//继续进行排序,直到每一组的个数为1时
Sort(a, low, i - 1);
Sort(a, i + 1, high);
}
//进行快速排序
void QuickSort(int a[], int len)
{
Sort(a, 0, len - 1);
}
int main()
{
int array[] = { 1,4,7,9,2,3,5,8 };
int len = sizeof(array) / sizeof(array[0]);
QuickSort(array,len);
for (int i = 0;i < len;++i)
printf("%d ", array[i]);
printf("\n");
return 0;
}
2.普通版本:
#define LENGTH 10
#include <stdio.h>
#include <stdlib.h>
void Swap(int *a, int low, int high)
{
int temp = a[low];
a[low] = a[high];
a[high] = temp;
}
int Partition(int *a, int low, int high)
{
int flag = a[low];
while (low < high)
{
while (low<high&&a[high]>flag)
--high;
Swap(a, low, high);
while (low < high&&a[low] < flag)
++low;
Swap(a, low, high);
}
return low;
}
void QSort(int *a, int low, int high)
{
int p;
if (low < high)
{
p = Partition(a, low, high);
QSort(a, low, p - 1);
QSort(a, p + 1, high);
}
}
void QuickSort(int *a)
{
QSort(a, 0, LENGTH - 1);
}
int main()
{
int i;
int array[LENGTH] = { 1,3,5,7,9,2,4,6,8,10 };
printf("Before Sorting:\n");
for (i = 0;i < LENGTH;++i)
printf("%d ", array[i]);
printf("\n");
QuickSort(array);
printf("After Sorting:\n");
for (i = 0;i < LENGTH;++i)
printf("%d ", array[i]);
printf("\n");
return 0;
}
3.优化版本:
#define LENGTH 10
#include <stdio.h>
#include <stdlib.h>
void Swap(int *a, int low, int high)
{
int temp = a[low];
a[low] = a[high];
a[high] = temp;
}
int Partition(int *a, int low, int high)
{
//三数取中,保证选到一个比较合适的flag;
int mid = low+(high-low)/2;
if (a[low] > a[high])
Swap(a, low, high);
if (a[mid] > high)
Swap(a, mid, high);
if (a[mid] > a[low])
Swap(a, mid, low);
int flag = a[low];
int p = a[low];
while (low < high)
{
while (low<high&&a[high]>flag)
--high;
//优化不必要的交换
a[low] = a[high];
while (low < high&&a[low] < flag)
++low;
a[high] = a[low];
}
a[low] = p;
return low;
}
void QSort(int *a, int low, int high)
{
int p;
if (low < high)
{
p = Partition(a, low, high);
QSort(a, low, p - 1);
QSort(a, p + 1, high);
}
}
void QuickSort(int *a)
{
QSort(a, 0, LENGTH - 1);
}
int main()
{
int i;
int array[LENGTH] = { 1,3,5,7,9,2,4,6,8,10 };
printf("Before Sorting:\n");
for (i = 0;i < LENGTH;++i)
printf("%d ", array[i]);
printf("\n");
QuickSort(array);
printf("After Sorting:\n");
for (i = 0;i < LENGTH;++i)
printf("%d ", array[i]);
printf("\n");
return 0;
}
4.尾递归优化
#define LENGTH 10
#include <stdio.h>
#include <stdlib.h>
void Swap(int *a, int low, int high)
{
int temp = a[low];
a[low] = a[high];
a[high] = temp;
}
int Partition(int *a, int low, int high)
{
int flag = a[low];
while (low < high)
{
while (low<high&&a[high]>flag)
--high;
Swap(a, low, high);
while (low < high&&a[low] < flag)
++low;
Swap(a, low, high);
}
return low;
}
void QSort(int *a, int low, int high)
{
int p;
while (low < high)
{
p = Partition(a, low, high);
QSort(a, low, p - 1);
//对QSort进行尾递归优化
low = p + 1;
}
}
void QuickSort(int *a)
{
QSort(a, 0, LENGTH - 1);
}
int main()
{
int i;
int array[LENGTH] = { 1,3,5,7,9,2,4,6,8,10 };
printf("Before Sorting:\n");
for (i = 0;i < LENGTH;++i)
printf("%d ", array[i]);
printf("\n");
QuickSort(array);
printf("After Sorting:\n");
for (i = 0;i < LENGTH;++i)
printf("%d ", array[i]);
printf("\n");
return 0;
}
因为采用迭代而不是递归,可以缩减堆栈深度,提高整体性能。