什么是快速排序
顾名思义,快速排序就是将一个一维数组里面的数进行一个从大到小的排序或者是从小到大的排序算法。
快速排序是分治法的一种经典示例。分治法将一个大问题分成多个小的问题,然后采用相同的算法分别解决这些小问题。
- 快速算法的操作
- 选择数组元素e作为分割元素,然后重新排列数组使得元素从1一直到 i-1都是小于或等于 e 的,元素 i 包括 e ,而元素从 i+1 一直到 n 都是大于或等于 e 的。
- 通过递归地采用快速排序方法,对从1到 i - 1 的元素进行排序。
- 通过递归地采用快速排序方法,对从 i + 1 到 n 的元素进行排序。
执行完第一步后,元素 e 处在正确的位置上。因为 e 左侧的元素全部都是小于或等于 e 的,所以一旦第二步对这些元素进行排序,那么这些小于或者等于 e 的元素也将会处在正确的位置上。类似的理由也可以应用于 e 右侧的元素。
快速排序的实现
该算法依赖于两个命名为low和high的标记,这两个标记用来跟踪数组内的位置。
- 开始,low指向数组中的第一个元素,而high指向末尾元素。
- 首先把第一个元素,也就是分割元素,复制给其他地方的一个临时存储单元,从而在数组中留出一个“空位”。
- 接下来从左到右移动high,直到high指向小于分割元素的数时停止。
- 然后把这个数复制给low指向的空位,这将产生一个新的空位(high指向的)。
- 现在从左向右移动low,寻找大于分割元素的数。
- 在找到时,把这个找到的数复制给high指向的空位。重复执行此操作,交替操作low和high直到两者在数组中间的某处相遇时停止。此时,两个标记都指向空位,只要把分割元素复制给空位就可以了。
程序
快速排序
/*Sorts an array of integers using Quicksort algorithm*/
#include<stdio.h>
#define N 10
void quicksort(int a[],int low,int high);
int split(int a[],int low,int high);
/*因为分割数组的代码有点长,所以把这部分代码放置在split函数中*/
int main()
{
int a[N], i;
printf("Enter %d numbers to be sorted:",N);
for(i=0;i<N;i++)
scanf("%d",&a[i]);
quicksort(a,0,N-1);
printf("In sorted order:");
for(i=0;i<N;i++)
printf("%d ",a[i]);
printf("\n");
return 0;
}
/*分割数组函数*/
int split(int a[],int low,int high){
int part_element=a[low];
//part_element是分割元素,用以在数组中留出空位
for(;;){
while(low<high&&part_element<=a[high])
high--;
/*如果low的数值小于high且分割元素小于等于high元素
那么就向左移动high一位(保证了分割元素左侧都是大的)*/
if(low>=high) break;//如果low元素比high元素大,则跳出循环
a[low++]=a[high];//注意这里是先a[low]=a[high]后再对low++
//将high的值复制到low指向的位置
while(low<high&&a[low]<=part_element)
low++;
/*如果low的数值小于high
且分割元素的值大于low
指向的元素的值,那么就向右移动low*/
if(low>=high) break;
a[high--]=a[low];
}
a[high]=part_element;
//跳出循环时high与low是重合的,将预留出的分割元素的值赋值到该位置
return high;
}
/*快速排序执行函数*/
void quicksort(int a[],int low,int high){
int middle;
if(low>=high) return;
middle=split(a,low,high);
/*从split函数可以看出,返回的是最后分割元素的位置
接下来分别对分割元素两侧再进行一次快速排序即可
*/
quicksort(a,low,middle-1);
quicksort(a,middle+1,high);
}
小结
总的来说,快速排序的思路就是始终保持分割元素左侧的元素小于分割元素,右侧的元素始终大于分割元素。在递归结束后依旧是这样一个大小关系。可以预想递归到最后每个元素都是分割元素,都符合这样的一个大小关系,这样就完成了排序。