数据结构与算法-快速排序

128 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第15天,点击查看活动详情

快速排序

快速排序可以说是冒泡排序的改进升级。冒泡排序方法是对数组中相邻两个数进行比较,而快速排序是分别从数组两端开始比较。

原理

快速排序方式是将一个数移动到当前数组中某个位置,保证该数据的左边都是小于它的数,右边都是大于它的数。一般情况下会先取数组的第一个数作为基准数来进行第一次排序。

【3,1,6,7,4,8,2,9,5,0】

例如初始数组状态下数字3是第一个数据,第一次排序要求以数字3使得排序结果是左边的数都小于3,右边的数都大于3。

image.png

1.分别从数组两端开始排序,用到双指针分别指向索引0索引9

2.首先索引9先从右边往左移动,因为基准值是3,对比后会发现索引9的值0就比3小停止移动,然后索引0从左往右移动。直到索引2的值6比3大停止移动。

image.png

3.停止移动后交换索引2索引9的数据

image.png

4.接着继续2的步骤继续在原索引位置上继续移动。

image.png

从右往左移动到数值2停下,从左往右移动到数值7发现比3大继续移动。直到移动到数据为7的索引3

image.png

交换后继续移动会发现4,8都大于3因此,3和2交换位置。然后就得出了以3为分割的左边范围和右边范围的数值排序数组。

image.png

接着继续对以上分割后的两个数组进行同样的排序操作知道分割介绍位置。

算法代码

i表示起始指针,j是末端指针,以数组第一个数为基准进行大小分类。分类后就是以基准为点划分两个大小数组。然后执行递归操作继续对两个数组进行大小分类直到排序结束。


void quickSort(int datas[],int start,int end){
    if(start >= end) return; 
    int i = start; // 起始
    int j = end; // 结束
    int first = datas[i]; // 基准数
    while(i < j){ // 下标没有重合时循环
        while(i < j && datas[j] >= first)  // 从最大下标开始对比 直到有小于或等于
         j--;
        while(i < j && datas[i] <= first) // 从最小下标开始对比 直到有小于或等于
         i++;
        if(j > i){  // 交换大小值
            int temp = datas[i];
            datas[i] = datas[j];
            datas[j] = temp;
        }
    }
    datas[start] = datas[i]; // 将基准值和当前最前面的指针换位
    datas[i] = first; // 将基准值和当前最前面的指针换位
    quickSort(datas,start, i -1); // 以基准值的左边数组排序
    quickSort(datas,i + 1, end); // 以基准值的右边数组排序
}

void main(){
     int datas[];
     int length = datas.length();
     quickSort(datas,0,length - 1);
}

总结

快速排序最差情况下大O记法和冒泡排序一样也是O(N2N^2),但平均情况下是O(NlogNNlogN)。和冒泡排序相比,快速排序交换时是跳跃性的。以一个基准点作为参考系将小数排在前面,大数排在后面。这样在每次交换时不会想冒泡排序不是以相邻数进行交换,少了比较和交换次数,效率就提升了。