排序算法——快速排序(快排)
排序算法有很多种,不同的算法有不同的时间复杂度和空间复杂度,对于某些特定的场合我们需要一些消耗时间少的的排序算法,有些时候我们需要消耗内存少的排序算法。今天我们要分析的快速排序算法。
- 快速排序的时间复杂度为O(nlogn)
- 空间复杂度为O(n)
快速排序是冒泡排序的改进算法,具有效率高的优点,非常值得学习。接下来我会分析其算法是如何实现(以下是基于我的理解,如果有什么问题欢迎提出)
简单描述这个过程
- 取出一个数为基准数。
- 分区,将大于基准数的排在右边,将小于基准数的排在左边,得到两个分区。
- 重复这个过程,将两个分区再分,一直循环重复,直到排序完成。
仔细描述这个过程,如下:
-
首先你会有一个需要的排序的数组,你需要确定一个基准数(所谓基准数就是一个标准,你需要要它和别的数进行比较,大于基准数的放到 right 所在位,小于基准数的放到 left 所在位)(这里好像挖坑了,前后呼应,看到后再回头看看前面收获会大一些),确定基准数,一般情况下是选择最左边的数作为一个基准数,也可以随便找一个数作为基准数。
-
对数组进行分区,分区的方法在第一点里面简要介绍了,首先你要得到数组的低位我记作low,之后得到数组的高位记为high。(这里应该会有疑问,低位是不是起始位为0,高位是不是最高位为数组长度减一,实际上我们的快速排序算法适用于将数组任何一个位置作为起点和终点的排序)判断数组是不是空数组,或者长度为一的数组,如果是直接返回就好。在我们进行排序时,需要确定未排序的左边的位置和右边的位置,实际上排序就是将左边位置上的元素和右边位置上的元素交换,如果左边的数大于基准值(记作temp),就将左边的数(left位置的数)放到右边(right位置上),当left和right移动到同一个元素上将这个元素变为基准值(temp),完成一次排序。此时有两个数组,一个大于基准值,一个小于基准值。一般从右边的开始排。
-
第三步很简单,就是找到两个数组的高位,低位,调用排序再次执行,直到排序完成。
图解如下
代码如下
public static void sort(int a[],int low,int high)
{
int left,right,temp;/*定义基准值,左位置,右位置*/
if(low>=high)
{
return;
}/*判断是不是为空或者有一个元素*/
left=low;/*将低位赋给左位置*/
right=high;/*将高位赋给右位置*/
temp=a[left];/*将首元素赋给基准值*/
while(left<right)/*循环条件,左边不大于右边*/
{
while(left<right&&a[right]>=temp)
{
right--;
}/*如果右边的数不小于temp,右位置往前移*/
a[left]=a[right];/*如果小于了temp,将右位置的数赋给左位置*/
while(left<right&&a[left]<=temp)
{
left++;
}/*接着判断左位置的数是否大于temp,不大于的话,左位置往后移*/
a[right]=a[left];/*如果大于temp,将左位置的数赋给右位置的数*/
}/*一直重复这些知道,左右位置重合*/
a[left]=temp;/*将基准数赋给重合位置*/
sort(a,low,left-1);/*将小于的分区重复这个操作,left-1为它的高位*/
sort(a,right+1,high);/*将大于的分区重复这个操作,right+1为它的低位*/
}/*快速排序完成*/
想要实践一下的小伙伴可以看看牛客网上的这个题目,可以试试自己写的排序可以通过吗?