十大排序算法 之 桶排序

96 阅读1分钟

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

今天的题目是桶排序算法。

思想:桶排序算法算是基于计数排序算法的升级版。每个桶是额外申请的空间,具有一定容量。待排序序列经过遍历放到桶里去,然后把不空的桶排序分别进行排序,最终完成整个序列的排序。

桶排序的最好时间复杂度为O(n+k),平均时间复杂度为O(n+k);最差时间复杂度为O(n2)。空间复杂度为O(n+k)。

代码实例:

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

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

typedef struct LL{
    struct LL *Next;
    int Val;
}NodeList;


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

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


//升序排序
int InsertSort(int Cnt,int* ArrPtr)
{
    for(int a = 1;a < Cnt;a++){
        for(int b = a;0 < b;b--){
            if(ArrPtr[b] < ArrPtr[b-1]) SWAP(ArrPtr[b],ArrPtr[b-1],int);
        }
    }
}
int BucketSort(int cnt,int *Arr)
{
    //分为十桶
    int i = 0;
    int MinVal = Arr[0];
    int MaxVal = Arr[0] + 1;
    NodeList BtVals[10];
    memset(BtVals,0,sizeof(NodeList)*10);


    for(i = 1;i < cnt;i++){
        if(Arr[i] < MinVal) MinVal= Arr[i];
        if(MaxVal < Arr[i]) MaxVal= Arr[i]+1;  //最大值增加1
    }
    int BtsInter = ((MaxVal-MinVal+1)%10) == 0? (MaxVal-MinVal + 1)/10:(MaxVal-MinVal+1)/10+1;
    NodeList *Temp = NULL;
    NodeList* OneNode ;
    for(i = 0;i < cnt;i++){
        Temp =  &BtVals[(Arr[i]-MinVal)/BtsInter];
        OneNode = (NodeList*)malloc(sizeof(NodeList));
        OneNode->Val = Arr[i];
        OneNode->Next = NULL;
        do{
            if(Temp->Next == NULL) {Temp->Next = OneNode; break;}
            
            if(Arr[i] <= Temp->Next->Val) {
                OneNode->Next = Temp->Next;
                Temp->Next = OneNode;
                break;
            }
        }while(Temp = Temp->Next);
    }
     int arrPos = 0;
    for(i = 0;i < 10; i++){
        Temp = (&BtVals[i])->Next;
        while(Temp){
            Arr[arrPos] = Temp->Val;
            arrPos++;
            Temp= Temp->Next;
        }
    }
    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[Bucket Sort]inputNum:");
    PrintNums();
    fprintf(stdout,"\n");

    BucketSort(ArrCnt,NumArr);

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

}

测试结果如下:

image.png

代码分了十个桶,桶的容量用数值跨度计算。在往桶里放入对象的时候,使用列表保存对象,列表有个好处是空间不连续,所以在加入链表的时候按照升序方式加入到链表。 在待排序列表全部放入桶中后,就可以按照顺序拿出已排好序的序列了。