思路
基数排序的主要思想:
借助多关键字进行排序的算法
算法的步骤主要是:分配和收集
基本思路:
1.先按元素的某位数作为关键字进行分配——关键字相同的放到同一队列
2. 然后对元素进行收集——按关键字的顺序对所有分配的元素进行连接
3. 对1、2步骤重复元素的位数次,最后收集所得的元素已排好序
相关概念
分类:
- LSD最低位优先
- MSD最高位优先
主要操作步骤:
- 分配
- 收集
前提条件:
- 基数
- 位数
- 值
适用情况:
-
字符串作为存储结构的数据
-
多关键字排序(如先按数学成绩排序,数学成绩相同的按语文成绩排序)
特点:
-
排序过程不需要进行关键字的比较
-
通用性较强,如可以将英语单词看成是一个26进制数,将车牌号看成一个36进制数等等,然后对其进行基数排序
实现
例子:输入5个3位的十进制数,对其进行基数排序。
#include<stdio.h>
#include<stdlib.h>
#define MAXD 3
#define MAXR 10
typedef struct node
{
char data[MAXD + 1];
struct node *next;
}DataNode;
//LSD
void radix_sort(DataNode * &p, int r, int d)
{
DataNode *head[MAXR], *rear[MAXR], *rp=NULL;
int i, j, k;
for (i=d-1; i >= 0; i--)
{
for (j=0; j<r; j++)
head[j] = rear[j] = NULL;
while (p != NULL)
{
k = p->data[i] - '0';
if (head[k] == NULL)
{
head[k] = rear[k] = p;
}
else
{
rear[k]->next = p;
rear[k] = p;
}
p = p->next;
}
for (j=0; j<r; j++)
if (head[j] != NULL)
if (p == NULL)
{
p = head[j];
rp = rear[j];
}
else
{
rp->next = head[j];
rp = rear[j];
}
rp->next = NULL;
}
}
DataNode *create_list(char str[][4], int n, int d)
{
int i, j;
DataNode *L, *p;
L = (DataNode *)malloc(sizeof(DataNode));
L->next = NULL;
for (i=n-1; i>=0; i--)
{
p = (DataNode *)malloc(sizeof(DataNode));
for (j=0; j<d; j++)
p->data[j] = str[i][j];
p->data[j] = '\0';
p->next = L->next;
L->next = p;
}
return L;
}
void print_list(DataNode *L)
{
DataNode *p = L->next;
while (p != NULL)
{
printf("%s\t", p->data);
p = p->next;
}
printf("\n");
}
int main()
{
char str[5][4];
int i;
DataNode *L = NULL;
for (i=0; i<5; i++)
scanf("%s", str[i]);
L = create_list(str, 5, 3);
print_list(L);
radix_sort(L->next, 10, 3);
print_list(L);
return 0;
}
算法分析
时间复杂度
算法进行元素的位数趟排序(假设位数为d),每一趟的主要操作是分配和收集,每趟分配对表中所有元素(假设n个)进行,每趟收集对基数个队列(假设基数为r)进行
最好、最坏和平均时间复杂度相同
综上,有:
O
(
d
(
n
+
r
)
)
O(d(n+r))
O(d(n+r))
空间复杂度
算法使用的临时指针数组与基数有关
O
(
r
)
O(r)
O(r)
稳定性
稳定