开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第18天,点击查看活动详情
思想: 找一个基准点,使用基准点,把无序序列分为左右两个无序序列,基准点处于正确位置。继续按照这个逻辑处理剩下的两个序列,直到变成有序序列。
流程:
- 使用第一个数值作为基准点,使用两个哨兵(序列的头尾两个指针)。
- 尾哨兵向头部寻找大于基准点的位置停下,头哨兵向尾部寻找小于基准点的位置停下,交换头尾哨兵的值,一定需要尾哨兵先寻找。
- 等待尾哨兵寻找的时候和头哨兵交汇时,交汇点的值和第一个基准点交换一下,完成一次处理。
- 剩余左右两个无序序列。继续按照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;
}
代码有点费劲,初次验证无错误,可拿来验证一下,有问题一起谈论。