快速排序
相较于冒泡排序每一趟处理使一个最大或者最小的元素确定最终位置,快速排序每次会使一个中间元素确定最终位置
下图是对quickSort函数中,low>high情况的解释
//快速排序:属于交换排序
//相较于冒泡排序每一趟处理使一个最大或者最小的元素确定最终位置,快速排序每次会使一个中间元素确定最终位置
//在待排序序列中任取一个元素作为基准,经过一趟排序后,会找到该基准的最终位置
/*时间复杂度:O(n*递归层数),空间复杂度: O(递归层数)
把n个元素组织成二叉树,二叉树的层数是递归调用的层数
(n个节点的二叉树,最小高度:log2n(向下取整)+1;最大高度:n)
时间复杂度:O(nlog2n),快速排序是所有内部排序算法中平均性能最优的排序算法
若每一次选中的基准元素,可将待排序序列划分成均匀的两个部分,递归深度最小
若初始序列有序甚至是逆序,则快速排序的性能最差(本文基准选择是子序列的第一个元素)*/
//不稳定排序
#include <iostream>
using namespace std;
//划分过程
int division(int a[],int low,int high){
//以子序列中的第一个元素作为基准
int base=a[low]; //赋值后的操作,可以认为low对应的位置空闲,可放入其他元素
//这里要注意,先控制移动的是high
while(low<high){
//让low所指位置的左边<基准,high所指位置的右边>基准(相等的情况不需要移动)
while(low<high&&a[high]>=base){
high--;
}
a[low]=a[high];
while(low<high&&a[low]<=base){
low++;
}
a[high]=a[low];
}
//low==high已经把待排序序列全部扫描,确定基准的最终位置
//强调一点,这里的最终位置就是该元素在最终有序序列中的位置,确定了就不动,即为最终
a[low]=base;
//以当前位置作为划分,分为左右两个子序列
return low;
}
//快速排序,递归
void quickSort(int a[],int low,int high){
/*low和high有三种情况(正文第一张图帮助理解:))
low>high:基准的左边没有元素
low==high:基准的左边或者右边还剩下一个元素
low<high:我们的正常情况,还有好多元素需要排序*/
if(low<high){
int base=division(a,low,high);
//递归地对左右待排序子序列重复操作,直至每个子序列内部只剩下一个元素或空
quickSort(a,low,base-1); //在左子序列中继续划分
quickSort(a,base+1,high); //在右子序列中继续划分
}
}
int main(){
int a[]={53,17,78,9,45,65,87,32,99,1};
int n=sizeof(a)/sizeof(int);
quickSort(a,0,n-1);
//输出
for(int i=0;i<n;i++){
cout<<a[i]<<" ";
}
return 0;
}
说明:本文为个人学习理解总结。