这里引用菜鸟教程中对快速排序的介绍
快速排序是C.R.A.Hoare于1962年提出的一种划分交换排序。它采用了一种分治的策略,通常称其为分治法(Divide-and-ConquerMethod)。
该方法的基本思想是:
- 1.先从数列中取出一个数作为基准数。
- 2.分区过程,将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边。
- 3.再对左右区间重复第二步,直到各区间只有一个数。
虽然快速排序称为分治法,但分治法这三个字显然无法很好的概括快速排序的全部步骤。因此我的对快速排序作了进一步的说明:挖坑填数+分治法:
分治法
void Qsort(int a[],int low,int high)//分治法,对序列,子序列,子序列的子序列......等进行递归排序
{
if(low<high)
{
int pivotloc=Partion(a,low,high);//挖坑填数后return中轴位置
Qsort(a,low,pivotloc-1);//递归排序轴左侧元素
Qsort(a,pivotloc+1,high);//递归排序轴右侧元素
}
}
挖坑填数
int Partion(int a[],int low,int high)//挖坑填数
{
a[0]=a[low];//把第一个 位置的元素赋给a[0],储存在a[0]中,a[low]被a[0]保存,可以被其他数覆盖,所以认为形成了第一个坑a[low]
int pivotkey=a[low];//选择第一个元素作为中轴的值
while(low<high)//在low==high时,两个坑其实是一个坑,中轴位置找到,此时循环结束
{
while(low<high&&a[high]>=pivotkey)high--;//当找到比中轴元素值小的值时,循环停止
a[low]=a[high];//把比中轴元素值小的值给挖好的坑,并在a[high]处挖出新坑
while(low<high&&a[low]<=pivotkey)low++;//当找到比中轴元素值大的值时,循环停止
a[high]=a[low];//把比中轴元素值大的值给挖好的坑,并在a[low]处挖出新坑
}
a[low]=a[0];//把一开始保存在中轴的值填到中轴位置的坑上
return low;//循环结束后返回找到的中轴的位置,pivotloc==low==high
}
完整的快速排序(就是把两段代码拼起来,比较直观)
int Partion(int a[],int low,int high)//挖坑填数
{
a[0]=a[low];//把第一个 位置的元素赋给a[0],储存在a[0]中,a[low]被a[0]保存,可以被其他数覆盖,所以认为形成了第一个坑a[low]
int pivotkey=a[low];//选择第一个元素作为中轴的值
while(low<high)//在low==high时,两个坑其实是一个坑,中轴位置找到,此时循环结束
{
while(low<high&&a[high]>=pivotkey)high--;//当找到比中轴元素值小的值时,循环停止
a[low]=a[high];//把比中轴元素值小的值给挖好的坑,并在a[high]处挖出新坑
while(low<high&&a[low]<=pivotkey)low++;//当找到比中轴元素值大的值时,循环停止
a[high]=a[low];//把比中轴元素值大的值给挖好的坑,并在a[low]处挖出新坑
}
a[low]=a[0];//把一开始保存在中轴的值填到中轴位置的坑上
return low;//循环结束后返回找到的中轴的位置,pivotloc==low==high
}
void Qsort(int a[],int low,int high)//分治法,对序列,子序列,子序列的子序列......等进行递归排序
{
if(low<high)
{
int pivotloc=Partion(a,low,high);//挖坑填数后return中轴位置
Qsort(a,low,pivotloc-1);//递归排序轴左侧元素
Qsort(a,pivotloc+1,high);//递归排序轴右侧元素
}
}
本文借助SDUTOJ平台的递归实验八进行测试
F - 数据结构实验之排序八:快速排序
Description
给定N(N≤10^5)个整数,要求用快速排序对数据进行升序排列,注意不得使用STL。
Input
输入数据第一行给出正整数N(≤10^5),随后给出N个整数,数字间以空格分隔。
Output
输出排序后的结果,数字间以一个空格间隔,行末不得有多余空格。
Sample
Input
8 49 38 65 97 76 13 27 49
Output
13 27 38 49 49 65 76 97
完善代码
#include <stdio.h>
#include <stdlib.h>
int Partion(int a[],int low,int high)
{
a[0]=a[low];
int pivotkey=a[low];
while(low<high)
{
while(low<high&&a[high]>=pivotkey)high--;
a[low]=a[high];
while(low<high&&a[low]<=pivotkey)low++;
a[high]=a[low];
}
a[low]=a[0];
return low;
void Qsort(int a[],int low,int high)
{
if(low<high)
{
int pivotloc=Partion(a,low,high);
Qsort(a,low,pivotloc-1);
Qsort(a,pivotloc+1,high);
}
}
int main()
{
int n,i,a[100001];
scanf("%d",&n);
for(i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
Qsort(a,1,n);
for(i=1;i<=n;i++)
{
if(i==n)printf("%d\n",a[i]);
else printf("%d ",a[i]);
}
return 0;
}
另外还可以把Praction和Qsort两个函数组合整理
void Qsort(int a[],int low,int high)
{
if(low<high)
{
int i,j;
a[0]=a[low];
int pivotkey=a[low];
i=low;//此处因为要保留原有的头和尾,所以不能直接low++或者high--
j=high;
while(i<j)
{
while(i<j&&a[j]>=pivotkey)j--;
a[i]=a[j];
while(i<j&&a[i]<=pivotkey)i++;
a[j]=a[i];
}
a[i]=a[0];
Qsort(a,low,i-1);
Qsort(a,i+1,high);
}
}
这样就是更加简洁的快速排序