基排序 / 桶排序 / 数字排序
# 原理
需要频繁进行分组重排,(类似于归并)适用于链表
可分为两种:
MSD,最高位优先 (Most Significant Digit first)
LSD,最低位优先 (Least Significant Digit first)
# 代码
//Definition for singly-linked list. | |
struct ListNode { | |
int val; | |
ListNode *next; | |
ListNode() : val(0), next(nullptr) {} | |
ListNode(int x) : val(x), next(nullptr) {} | |
ListNode(int x, ListNode *next) : val(x), next(next) {} | |
}; |
class Solution { | |
public: | |
ListNode* sortList(ListNode* head) | |
{ | |
ListNode* dummyhead=new ListNode(0,head); | |
ListNode* p=dummyhead; | |
while(p->next!=nullptr) | |
{ | |
p->next->val+=100000; | |
p=p->next; | |
} | |
vector<queue<ListNode*>>vec(10); // 按 0~9 分组 | |
for(int i=1;i<=100000;i*=10) // 这里是 6 位数,共 6 趟 | |
{ | |
int flag=0; | |
while(dummyhead->next!=nullptr) | |
{ | |
if(dummyhead->next->val/(i*10)!=0) | |
flag=1; | |
vec[dummyhead->next->val/i%10].push(dummyhead->next); | |
dummyhead->next=dummyhead->next->next; | |
} | |
ListNode* p=dummyhead; | |
for(int j=0;j<10;++j) // 将每个组节点连接起来 | |
{ | |
while(!vec[j].empty()) | |
{ | |
vec[j].front()->next=p->next; | |
p->next=vec[j].front(); | |
p=p->next; | |
vec[j].pop(); | |
} | |
} | |
if(flag==0) | |
break; | |
} | |
p=dummyhead; | |
while(p->next!=nullptr) | |
{ | |
p->next->val-=100000; | |
p=p->next; | |
} | |
ListNode* ret=dummyhead->next; | |
delete dummyhead; | |
return ret; | |
} | |
}; |
# 复杂度
设有 个待排序记录,关键字位数为,每位有 种取值。则排序的趟数是; 在每一趟中:
- 链表初始化的时间复杂度:;
- 分配的时间复杂度:;
- 分配后收集的时间复杂度:;
则链式基数排序的时间复杂度为:
在排序过程中使用的辅助空间是: 个链表指针, 个指针域空间,
实际应用中 远小于,可以得到时间复杂度为:
则空间复杂度为:
当 n 很大,d 比较小小,基数排序可以比归并、快排性能更好
基排序是稳定排序。