开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第22天,点击查看活动详情
基数排序是一种非基于比较模式下对整数对象的排序算法。
思想:
的数字表达模式,可以按照二进制,十进制或者八进制,叫做基数。按照每一权位的数位,从lsd或者msd方式,分割为不同的区间,循环分割完全部的权位,就可以完成排序。
它的平均最好和最差时间复杂度是O(n*k),空间复杂度为O(k + N)。每个对象都经过分类,按照顺序再次复原,不出现相对对象位置交换的现象,所以算法是稳定的。
流程:
1.按照lsd方式,从最小的权位,按照申请基数申请额外空间,同一数值下可能会有几个待比较对象,此处可以使用链表保存数值。
2.按照1逻辑,比较更高权位。
3.遍历完成所有权位,从额外空间取回对象,排序完成。
代码示例:
#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 b = 0;b < ArrCnt;b++){
fprintf(stdout," %d-",NumArr[b]);
}
}
void ClearList(NodeList * NodArr)
{
NodeList * Temp = NULL;
NodeList * NodePtr = NULL;
for(int i = 0;i < 10; i++){
NodePtr = NodArr[i].Next;
NodArr[i].Next = NULL;
while(NodePtr){
Temp = NodePtr;
NodePtr = NodePtr->Next;
free(Temp);
}
}
}
int InsertNodeList(int Val,int tt,NodeList *NodePtr)
{
NodeList * OneNode = (NodeList*)malloc(sizeof(NodeList));
OneNode->Val = Val;
OneNode->Next = NULL;
while(NodePtr){
if(NodePtr->Next == NULL){
NodePtr->Next = OneNode;
break;
}
NodePtr= NodePtr->Next;
}
return tt == 0?0:1;
}
int RadixSort(int cnt,int *Arr)
{
fprintf(stdout,"RadixSort cnt:%d-\n",cnt);
NodeList *Temp = NULL;
NodeList BtVals[10];
memset(BtVals,0,sizeof(NodeList)*10);
int res = 1;
int arrPos = 0;
int fac = 1; //位权
while(res != 0){
res = 0;
for(int a = 0;a <cnt;a++){
res +=InsertNodeList(Arr[a],Arr[a]/fac,&BtVals[Arr[a]/fac%10]);
}
fprintf(stdout," res:%d-\n",res);
//把缓存数据全部还原去原空间
arrPos = 0;
for(int i = 0;i < 10; i++){
Temp = (&BtVals[i])->Next;
while(Temp){
Arr[arrPos] = Temp->Val;
arrPos++;
Temp= Temp->Next;
}
}
ClearList(BtVals);
fac *=10;
}
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[Radix Sort]inputNum:");
PrintNums();
fprintf(stdout,"\n");
RadixSort(ArrCnt,NumArr);
fprintf(stdout,"\n\t\t\t\tresult:");
PrintNums();
fprintf(stdout,"\n");
return 0;
}
测试结果:
数据结构使用了 桶排序中声明的链表结构,结构简单,使用方便。
接口上声明了两个,一个用来插入对象,一个用来清空申请的空间。并且再每次循环主动记录是否已经解析过全部权位。
使用lsd模式,从低权位遍历查找到高权位。
代码可以直接编译使用,有兴趣可以复制出来,加加日志,感受一下过程。
这个和桶排序思想一致,只是桶的实现方案不一样,写的匆忙,如有错误,请联系我。