我个人认为,快速排序是一个十分经典的排序方法,顾名思义,快排确实比其他普通排序算法要快,空间复杂度也不是特别高。
所谓快排,先讲一下大体上的操作,我先让待排序序列的第一个元素作为一个“哨兵”,用这个哨兵把序列分成两部分,前一部分比该哨兵的值小,后一部分比该哨兵的值要大。然后我分别对前后两个序列分别快排,也就是重复此操作。但是要完成快排还要解决一件事,就是如何用哨兵把原序列分成两个。其实分成两部分的过程就相当于对于待排序序列每次操作都在“挖空填空”,“挖空填空”是什么鬼?明白了挖空填空也就掌握了快排。首先,前面说过哨兵是第一个元素的值,这个值存在新定义的元素key中,相当于在第一个位置挖了一个空,我用left标记从起始点到left为已找到的比key小的序列,用right标记从right到末尾为比key大的序列。从后往前遍历这个序列,直到找到比key小的数,把这个位置的值挖出来,填到上一个空里,当前位置就成了新空。然后从前往后遍历数组直到找到比key大的数,停下来,把该位置的数填到上一个空里。然后再从后往前,再从前往后……,直到right<=left停止。最后把key存到最后一个空里。这就完成了一次操作。然后就像上面所说的那样,分别对前后两个序列分别快排,进行的操作的相同的。快速排序的平均时间复杂度为O(nlgn),其相对不稳定。详情见代码。
#include<cstdio>
#define maxn 1000+10
void Swap(int &a, int &b)
{
int x = a;
a = b;
b = x;
}
int Quick_Sort(int a[], int left, int right)//用到了递归
{
if(left < right)
{
int i = left, j = right, key = a[left];
while(i < j)
{
while(i<j && a[j]>=key)//从后往前找,直到找到比key小的数
j--;
if(i < j)
a[i++] = a[j];//填空
while(i<j && a[i]<=key)//从前往后找,直到找到比key大的数
i++;
if(i < j)
a[j--] = a[i];// 填空
}
a[i] = key;
Quick_Sort(a, left, i-1);
Quick_Sort(a, i+1, right);
}
}
int main()
{
int num[maxn];
int n;
scanf("%d", &n);
for(int i = 0; i < n; i++)
{
scanf("%d", &num[i]);
}
Quick_Sort(num, 0, n);
printf("%d", num[0]);
for(int i = 1; i < n; i++)
{
printf(" %d", num[i]);
}
printf("\n");
return 0;
}