算法思想:从待排序的序列中选取一个元素(通常情况下选取第一个元素)作为枢轴,其关键字设为base,然后将其余小于base的元素移到前面,将大于等于base的元素移到后面,结果将待排序的元素序列分成了两个子序列,最后将关键字base插入分界线的位置,此过程被称为一趟快速排序。
对于分割后的子序列继续按上面的原则进行分割,直到所有子序列的长度不超过1为止,此时,待排序的记录序列变成了一个有序序列。
举例:3 5 1 2 10 4 7 8 9 6,对于一个长度为10的无序序列选择第一个元素3作为base。
从右到左寻找小于3的元素找到a[3]=2<3;将2移动到空单元a[0]处。
_ 5 1 2 10 4 7 8 9 6——>2 5 1 _ 10 4 7 8 9 6
从左到右寻找大于3 的元素找到a[1]=5>3;将5移动到空单元a[3]处。
2 5 1 _ 10 4 7 8 9 6——>2 _ 1 5 10 4 7 8 9 6
然后再从左到右寻找小于3的元素找到a[2]=1<3,将1移动到空单元a[1]处。
2 _ 1 5 10 4 7 8 9 6——>2 1 _ 5 10 4 7 8 9 6
最后将base值放在空单元a[2]处得到第一次快速排序结果:2 1 3 5 10 4 7 8 9 6
核心代码:
void quickSort(int a[],int begin,int end)
{
if(begin<end)
{
int base=a[begin];//选择基准为数组第一个元素
int i=begin;
int j=end;
while(i<j){
while(i<j&&a[j]>base)//序列从右到左寻找小于base的元素
j--;
if(i<j){//找到小于base的元素,将其赋给空单元a[i]
a[i]=a[j];
i++;
}
while(i<j&&a[i]<base)//从左到右寻找大于base的元素
i++;
if(i<j)//找到大于或等于base的元素,将其送入空单元a[j]
{
a[j]=a[i];
j--;
}
}
a[i]=base;
//递归
quickSort(a,begin,i-1);//base左侧表进行上述快速排序
quickSort(a,i+1,end);//base右侧表进行上述快速排序
}
}
最好情况:每一趟将序列一份为二,正好在序列中间,将序列分为两个大小相等的子序列,类似于折半查找,此时的时间复杂度为O(nlog2n);
最坏情况:已经排好序,第一趟经过n-1次比较,第一个元素定在原位置,左边的子序列为空序列,右边子序列为n-1个元素;第二趟n-1个元素经过n-2次比较,第二个元素定在原位置,左边子序列为空序列,右边子序列为n-2;依次类推,共需要进行n-1次排序,比较次数:
时间复杂度为O(n^2);
快速排序递归算法的执行过程对应一棵二叉树,理想情况下是一棵完全二叉树,递归工作栈的大小与递归调用二叉树深度对应,平均空间复杂度为O(log2n)
选择基准法:
1.为了避免枢轴元素为最大或最小值,可以采用三元素值取中间值的办法,如{47,78,99,25,60},从47,99,60中选择60。
2.随机选取某个元素作为枢轴元素。
快速排序是一种不稳定排序。
C语言可运行代码:
#include<stdio.h>
void printArray(int a[],int n)
{
for(int i=0;i<n;i++)
printf("%-4d",a[i]);
printf("\n");
}
void quickSort(int a[],int begin,int end)
{
if(begin<end)
{
int base=a[begin];//选择基准为数组第一个元素
int i=begin;
int j=end;
while(i<j){
while(i<j&&a[j]>base)//序列从右到左寻找小于base的元素
j--;
if(i<j){//找到小于base的元素,将其赋给空单元a[i]
a[i]=a[j];
i++;
}
while(i<j&&a[i]<base)//从左到右寻找大于base的元素
i++;
if(i<j)//找到大于或等于base的元素,将其送入空单元a[j]
{
a[j]=a[i];
j--;
}
}
a[i]=base;
//递归
quickSort(a,begin,i-1);//base左侧表进行上述快速排序
quickSort(a,i+1,end);//base右侧表进行上述快速排序
}
}
int main(){
int a[10];
printf("please enter 10 numbers:\n");
for(int i=0;i<10;i++)
scanf("%d",&a[i]);
printf("the array before sort:\n");
printArray(a,10);
quickSort(a,0,9);
printf("the array after sort:\n");
printArray(a,10);
return 0;
}
运行结果:
java可运行代码:
package one;
import java.util.Scanner;
public class quickSort {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int[] a = new int[10];
System.out.println("please enter 10 numbers");
for (int i = 0; i < a.length; i++)
a[i] = input.nextInt();
System.out.println("the array before sort:");
print(a);
System.out.println();
sort(a,0,a.length-1);
System.out.println("the array after sort:");
print(a);
}
public static void print(int[] a) {
for (int i = 0; i < a.length; i++)
System.out.printf("%-4d", a[i]);
}
public static void sort(int[] a, int begin, int end) {
if(begin<end)
{
int base=a[begin];//选择基准为数组第一个元素
int i=begin;
int j=end;
while(i<j){
while(i<j&&a[j]>base)//序列从右到左寻找小于base的元素
j--;
if(i<j){//找到小于base的元素,将其赋给空单元a[i]
a[i]=a[j];
i++;
}
while(i<j&&a[i]<base)//从左到右寻找大于base的元素
i++;
if(i<j)//找到大于或等于base的元素,将其送入空单元a[j]
{
a[j]=a[i];
j--;
}
}
a[i]=base;
//递归
sort(a,begin,i-1);//base左侧表进行上述快速排序
sort(a,i+1,end);//base右侧表进行上述快速排序
}
}
}
运行结果: