快速排序(Quick Sort)是对冒泡排序的一种改进。
基本思想:通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,再对两部分记录分别进行继续排序,使得整个记录有序。
首先任选一个记录(通常选第一个记录)作为枢轴(或支点)privot。
一趟快速排序的做法:
附设两个指针low和high,它们的初始值分别为low和high,设枢轴记录的关键字为privotkey,
首先从high所指的位置起向前搜索找到第一个关键字小于privotkey的记录,和枢轴记录互换;
然后从low所指的位置起向后搜索找到第一个关键字大于privotkey的记录,和枢轴记录互换;
重复这两步直至low=high为止。
49 38 65 97 76 13 27 49
初始关键字:49 38 65 97 76 13 27 49
high 49 = 49
27 < 49 互换 27 38 65 97 76 13 49 49
low 38 < 49
65 > 49 互换 27 38 49 97 76 13 65 49
high 13 < 49 互换 27 38 13 97 76 49 65 49
low 97 > 49 互换 27 38 13 49 76 97 65 49
high 76 > 49
low = high 49 = 49 {27 38 13} 49 {76 97 65 49} 完成一趟排序
一次划分结果:{27 38 13} 49 {76 97 65 49}
两边分别进行快速排序: {13} 27 {38}
{49 65} 76 {97}
有序序列{13 27 38 49 49 65 76 97}
核心代码:
int Partition(int arr[], int low, int high){
// 选取第一个数作为基准数
int base = arr[low];
while(low < high){
//从high开始,向左遍历,直到找到小于基准数的元素,并将此数放到low位置
while(low < high && arr[high] >= base)
high --;
Swap(arr,low,high);
//从low开始,向右遍历,直到找到大于基准数的元素,并将此数放到high位置
while(low < high && arr[low] <= base)
low ++;
Swap(arr,low,high);
}
return low;
}
void QuickSort(int arr[], int low, int high){
int base;
if(low < high){
//将数组一分为二
base = Partition(arr, low, high);
//对低子表递归排序
QuickSort(arr, low, base-1);
//对高子表递归排序
QuickSort(arr, base+1,high);
}
}
完整代码:
#include<stdio.h>
#include<stdlib.h>
void Swap(int arr[] ,int low ,int high)
{
int tmp;
tmp=arr[low];
arr[low]=arr[high];
arr[high]=tmp;
}
int Partition(int arr[], int low, int high){
// 选取第一个数作为基准数
int base = arr[low];
while(low < high){
//从high开始,向左遍历,直到找到小于基准数的元素,并将此数放到low位置
while(low < high && arr[high] >= base)
high --;
Swap(arr,low,high);
//从low开始,向右遍历,直到找到大于基准数的元素,并将此数放到high位置
while(low < high && arr[low] <= base)
low ++;
Swap(arr,low,high);
}
return low;
}
void QuickSort(int arr[], int low, int high){
int base;
if(low < high){
//将数组一分为二
base = Partition(arr, low, high);
//对低子表递归排序
QuickSort(arr, low, base-1);
//对高子表递归排序
QuickSort(arr, base+1,high);
}
}
int main(){
int arr[] = {49,38,65,97,76,13,27};
int length=0;
length=sizeof(arr)/sizeof(arr[0]);
int i,j;
printf("排序前:\n");
for(i = 0; i < length; i++){
printf("%d ",arr[i]);
}
printf("\n排序后:\n");
QuickSort(arr, 0, length-1);
for(j = 0; j < length; j++){
printf("%d ",arr[j]);
}
printf("\n");
return 0;
}
算法性能
时间复杂度
当数据有序时,以第一个关键字为基准分为两个子序列,前一个子序列为空,此时执行效率最差。
而当数据随机分布时,以第一个关键字为基准分为两个子序列,两个子序列的元素个数接近相等,此时执行效率最好。
所以,数据越随机分布时,快速排序性能越好;数据越接近有序,快速排序性能越差。
空间复杂度
快速排序在每次分割的过程中,需要 1 个空间存储基准值。而快速排序的大概需要 NlogN次的分割处理,所以占用空间也是 NlogN 个。
算法稳定性
不稳定。在快速排序中,相等元素可能会因为分区而交换顺序,所以它是不稳定的算法。