快速排序是基于分治模式的。
一.基本思路:
1.找出一个基准数;
2.重新排列数列,把比基准数小的放在前面,比基准数大的放在后面,分割结束后,基准数就是中间数,此操作也成为分割操作;
3.递归的把被基准数分开的两个序列重新排序。
快速排序是递归思想的经典运用。
该算法是由东尼·卡尔先生在1962年提出来的。
二.分解方法:
数组A[p…r]被划分成两个可能空的子数组A[p..q-1]<=A[q]<=A[q+1..r].
三.解决方法:
通过递归调用进行快速排序。
四.合并:
因为两个子数组是就地排序的,所以他们的合并不需要进行操作。
五.伪代码:
版本一:
因为选择排序算法有很多种版本,此处首先选择《算法导论》中的所用的那一版,即使用数组的最后一个元素作为主元进行排序
QUICKSORT(A,p,r) If(p<r) Then q←PARTION(A,p,r) QUICKSORT(A,p,q-1) QUICKSORT(A,q+1,r) PARTION(A,p,r) x←A[r] i←p-1 forj←p to r-1 do if A[j]<=x then i←i+1 exchange A[i]A[j] exchange A[i+1]A[r] return i+1
六.源代码实现:
#include<stdio.h> #include<stdlib.h> #define MAX 8 void exchange(int *x,int *y)//此处必须用指针实现,否则由于函数的拷贝不能改变调用函数的参数值 { int temp; temp=*x; *x=*y; *y=temp; } int partion(int v[],int p,int r) { int x=v[r]; int i=p-1; int j; for(j=p;j<=r-1;j++) { if(v[j]<x) { i++; exchange(&v[i],&v[j]); } } exchange(&v[i+1],&v[r]); return i+1; } void QuickSort(int v[],int p,int r) { int q=0; if(p<r) { q=partion(v,p,r); QuickSort(v,p,q-1); QuickSort(v,q+1,r); } } int main() { int v[MAX]; for(int i=0;i<MAX;i++) scanf("%d",&v[i]); QuickSort(v,0,MAX-1); for(int j=0;j<MAX;j++) printf("%d\t",v[j]); system("pause"); return 0; }
七.运行结果:
八.算法演示:
附:
版本二:
把数组的第一个元素作为主元进行排序
伪代码:
QUICKSORT
i←p
j←r
x←v[p]
if p<r
while i<j
while v[j]>=x
j-- //从右边向左边数找到第一个比主元小的数
if i<j
v[i]=v[j] //把找到的数赋给左边被“挖掉的”数
i++
while v[i]<x
i++ //从左边向右边找,找到第一个比主元大的数
if i<j
v[j]=v[i] //再把找到的数赋给右边“被挖掉的”数
j--
x←v[i]
QUICKSORT //再递归
源代码实现:
#include<stdio.h> #include<stdlib.h> #define MAX 8 void QuickSort(int v[],int p,int r) { if (p<r) { int x=v[p]; int i=p; int j=r; while(i<j) { while(v[j]>=x&&i<j) j--; if(i<j) v[i++]=v[j]; while(i<j&&v[i]<x) i++; if(i<j) v[j--]=v[i]; } v[i]=x; QuickSort(v,p,i-1); QuickSort(v,i+1,r); } } int main() { int v[MAX]; for(int i=0;i<MAX;i++) scanf("%d",&v[i]); QuickSort(v,0,MAX-1); for(int j=0;j<MAX;j++) printf("%d\t",v[j]); system("pause"); return 0; }
运行结果
算法演示:
从上图可以看出最终此数列被2分为两个子数列,然后以此类推进行递归排序,请读者自己进行后面的步骤
九.总结:
关于快速排序的版本还有很多,但无非是选择主元的方式和位置不同罢了,这里只选择两个典型的方法进行初步介绍,至于算法性能等进阶的问题,会在后面继续进行详细介绍。
版本一和版本二,理解任意一种即可,但个人认为第二种似乎比较容易理解,且代码也简洁明了,值得学习。