快速排序
前言
快速排序算法是托尼·霍尔(Tony Hoare)在1962年提出来的,他是快速排序之父,是1980年图灵奖得主。本篇文章将介绍通过递归的不同写法的方法和非递归的方法来实现简单的快速排序。
一、快速排序的基本思想
快速排序是一种二叉树结构的交换排序方法,其基本思想为:任取待排序元素序列中的某元素作为基准值(后文称也其为key) ,按照该排序码将待排序集合 分割成两子序列 ,左子序列中所有元素均小于基准值,右子序列中所有元素均大于基准值,然后最左右子序列重复该过程,直到所有元素都排列在相应位置上为止。
这一过程相当于二叉树的前序遍历,先让基准值排列在相应位置,然后分割子序列,每次分割左右子序列都排好一个基准值,然后再分割左右子序列,直到序列中只有一个元素时即为最小子问题,当每一个根都排在了相应位置,那么序列就变得有序了,所以很容易就想到了用递归来实现快速排序这一算法。
上面介绍的是单趟排序后将key排到了正确的位置上,我们要递归进行多次单趟排序,每次单趟排序选出key排到相应位置,每排好key的位置后,就将key的左右分成两个区间,再在左右区间中选出key排好后再分成左右区间,如此递归,分而治之,最后区间内只剩下一个元素时(只有一个元素可以认定为有序)或者区间内没有元素时是最小子问题。最后每个元素都排在了相应的位置上,数组就变有序了。
过程视频动画:【三分钟学会快速排序】
https://www.bilibili.com/video/BV1j841197rQ?vd_source=bd4386a37988e79a78cd8a71d55cb566
我们可以从上面的递归展开图看到,我们每次在区间内排出好key的位置,然后再在key的左右区间进行递归,再次排出key的位置,再分成两个子区间,每次递归就排好了一个值,直到区间内只有一个元素或者没有元素时结束递归。这样下来,我们的数组就变有序了。
一次过程的函数
int qsort(int left,int right){
if(left >= right) return left;
int t;t = a[left];
while(left < right){
while(left < right && a[right] >= t){
right -- ;
}
a[left] = a[right];
while(left < right && a[left]<=t){
left ++;
}
a[right] = a[left];
}
a[right] = t;
return right;
}
递归函数:
void qqsort(int left,int right){
if(left > right){
return ;
}
int tmp = qsort(left,right);
qqsort(left,tmp-1);
qqsort(tmp+1,right);
}
完整程序:
#include<bits/stdc++.h>
using namespace std;
int a[100];
int n;
int qsort(int left,int right){
if(left >= right) return left;
int t;t = a[left];
while(left < right){
while(left < right && a[right] >= t){
right -- ;
}
a[left] = a[right];
while(left < right && a[left]<=t){
left ++;
}
a[right] = a[left];
}
a[right] = t;
return right;
}
void qqsort(int left,int right){
if(left > right){
return ;
}
int tmp = qsort(left,right);
qqsort(left,tmp-1);
qqsort(tmp+1,right);
}
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
qqsort(1,n);
for(int i=1;i<= n;i++){
cout<<a[i]<<" ";
}
}
示例:
input:
5 5 4 2 3 9
output:
2 3 4 5 9