开启掘金成长之旅!这是我参与「掘金日新计划 · 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;
}
测试结果如下:
代码分了十个桶,桶的容量用数值跨度计算。在往桶里放入对象的时候,使用列表保存对象,列表有个好处是空间不连续,所以在加入链表的时候按照升序方式加入到链表。 在待排序列表全部放入桶中后,就可以按照顺序拿出已排好序的序列了。