十大排序算法 之 快速算法

83 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第18天,点击查看活动详情

思想: 找一个基准点,使用基准点,把无序序列分为左右两个无序序列,基准点处于正确位置。继续按照这个逻辑处理剩下的两个序列,直到变成有序序列。

流程:

  1. 使用第一个数值作为基准点,使用两个哨兵(序列的头尾两个指针)。
  2. 尾哨兵向头部寻找大于基准点的位置停下,头哨兵向尾部寻找小于基准点的位置停下,交换头尾哨兵的值,一定需要尾哨兵先寻找。
  3. 等待尾哨兵寻找的时候和头哨兵交汇时,交汇点的值和第一个基准点交换一下,完成一次处理。
  4. 剩余左右两个无序序列。继续按照123流程循环处理序列,直至完成排序。

特点:平均时间复杂度是O(nlogn),最差时间复杂度是O(n2)。在使用基准点分左右两个序列的时候,可能造成对象的相对顺序变化,所以快速排序是不稳定的。

代码实例:

#include<stdio.h>
#include <stdlib.h>
#include<unistd.h>
#include <string.h>
#include <errno.h>

#define SWAP(a1, a2, type) do {type temp = a1; a1 = a2; a2 = temp;} while(0)



int ArrCnt = 0;
int NumArr[200] = {0};

void PrintNums()
{
    for(int i = 0;i < ArrCnt;i++){
        fprintf(stdout," %d-",NumArr[i]);
    }
}


int inQuickSort(int *arr ,int cnt)
{
    if(cnt <= 1) return 0;  //设置退出递归判断
    int i = 0;
    for(int j = cnt - 1;i < j; j--){

        //匹配 相等的基准点,作用 把这些点扔到前段序列里
        if(arr[0] >= arr[j]){
            fprintf(stdout,"right arr[%d]=%d-",j,NumArr[j]);
            for(i = 0;i < j;i++){
                if(arr[0] < arr[i]){
                    fprintf(stdout,"left arr[%d]=%d-\n\n",i,NumArr[i]);
                    SWAP(arr[j],arr[i],int);

                    比较一次列表,进行下一次比较
                    break;                  
                }
            }
        }
    }
    SWAP(arr[0],arr[i],int);

    //不计基准点位置,前段序列排序
    inQuickSort(arr,i);

    //跳过基准点位置,后段序列排序
    inQuickSort(&arr[i+1],cnt -i -1);  
    return 0;
}
//升序排序
int QuickSort(int Cnt,int* ArrPtr)
{
    inQuickSort(ArrPtr,Cnt);
    return 0;
}
int main(int argc, char** argv)
{
    if(argc == 1) {
        fprintf(stderr,"%s:need a some arg\n",argv[0]);
        exit(1);
    }
    int CntTemp = ArrCnt = argc -1;

    for(int i = 0;i < ArrCnt;i++){
        NumArr[i] = atoi(argv[i+1]);
    }
   
    fprintf(stdout,"\t\t\t\t[Merge Sort]inputNum:");
    PrintNums();
    fprintf(stdout,"\n");

    QuickSort(ArrCnt,NumArr);

    fprintf(stdout,"\n\t\t\t\tresult:");
    PrintNums();
    fprintf(stdout,"\n");
    return 0;

}

代码有点费劲,初次验证无错误,可拿来验证一下,有问题一起谈论。