快排分为单路快排和多路快排
定义:在待排序列中L[1…n]中,任取一个元素pivot作为基准(一般取第一个元素),通过一趟排序将待排序表 划分 为独立的两部分,使得在L[K]左右两边的元素,L[1…K-1]中所有的元素都小于pivot,L[k+1…n]中的所有元素大于等于pivot,则pivot放在了其最终位置L[k]上,此过程为一趟快速排序。
(即array[low]<pivot<array[high])
快排是对冒泡的改进,基本思想分治,代码用到递归
关键在于划分操作。和冒泡排序一样,每次确定一个元素的最终位置。
和冒泡排序的不同是,快排是(不稳定算法)
空间复杂度与递归调用的栈的深度有关
平均为O(logn)
最坏为O(n)
平均、最优:时间复杂度为O(nlogn)
最坏才和冒泡一样为O(n2)
时间复杂度
快排的运行时间与划分是否对称有关,
若初始序列基本有序或逆序,那么为O(n2)
若初始序列分布都差不多,那么为O(nlogn)
一般快排的实现有两种,单路快排和双路快排,下面是C语言实现的单路快排
C语言实现版本
//其中L[0]不放元素
#include<stdio.h>
void QuickSort(int *a,int low,int high);
int Partition(int *a,int low,int high);
int main(){
int a[8]={8,7,6,5,4,3,2,1};
int i;
QuickSort(a,0,7);
for(i=0;i<8;++i){
printf("%d ",a[i]);
}
return 0;
}
void QuickSort(int *a,int low,int high){
int pivotpos;
if(low<high){
pivotpos=Partition(a,low,high);
QuickSort(a,low,pivotpos-1);
QuickSort(a,pivotpos+1,high);
}
}
int Partition(int *a,int low,int high){
int pivot=a[low];
while(low<high){
while(low<high&&pivot<=a[high])
--high;
a[low]=a[high];
while(low<high&&pivot>=a[low])
++low;
a[high]=a[low];
}
a[low]=pivot;
return low;
}
java单路快排
public class test {
public static void main(String[] args) {
int[] a = new int[]{1,3,5,7,2,4,6,8};
// int[] a = new int[]{9,7,6,5,4,3,2,1};
int n = a.length-1;
quickSort(a,0,n);
for (int i=0;i<n;i++){
System.out.println(a[i]);
}
}
public static void quickSort(int array[],int left,int right){
if(left<right){
int mid = quickSort2(array,left,right);
quickSort(array,left,mid-1);
quickSort(array,mid+1,right);
}
}
public static int quickSort2(int[] array,int left,int right){
//目的就是让左边的元素都是小于基准值,右边的元素都大于基准值
int pivot = array[left];
//先来右边,因为基准值在左边
while(left<right){
while(array[right]>=pivot&&left<right){
right--; //如果右边的元素大,那么就没问题,很守规矩,可以过
//就是不用换,等于需要换吗,等于也不需要换
}
array[left]=array[right];
while(array[left]<=pivot&&left<right){
left++;
}
array[right] = array[left];
}
array[left] = pivot;
return left;
}
}
对算法最好的理解方式就是手动的模拟算法