桶排序(稳定的排序算法)
桶排序 (Bucket sort)或所谓的箱排序,是一个排序算法,工作的原理是将数组分到有限数量的桶子里。每个桶子再个别排序(有可能再使用别的排序算法或是以递归方式继续使用桶排序进行排序)。
基本原理
把待排序序列中的数据根据函数映射方法分配到若干个桶中,在分别对各个桶进行排序,最后依次按顺序取出桶中的数据。
适用于数据分配均匀,数据比较大,相对集中的情况。
映射函数
映射函数要根据数据情况合理的适用,最好可以达到每个桶中只有一个元素,使得时间复杂度最优,但是空间复杂度太高。
假设数据都为3位的正整数,那么对应的映射函数可以为f(x)=x/100.即把百位相同的数划到同一数据块;
假设数据为2和3位的正整数,那么对应的映射函数可以为f(x)=x/100.即把百位相同的数划到同一数据块;
如下图:
代码如下(C语言)
#include <stdio.h>
#include <stdlib.h>
/* struct node *next:链表里用于指向下一个节点的指针,也就是指向下一个(节点)结构类型的指针。
struct node {} 是一种结构,有两个成员,一个成员是 int 数据,另一个是指向下一个 node 结构的指针。 */
typedef struct node {
int num;
struct node *next;
}KeyNode;
void bucket_sort(int a[],int size,int bucket_size) {
int i,j;
//这是一个结构体指针的数组,数组内都是指针,还要分配内存,为结构体指针数组分配大小为bucket_size的内存空间
//使用二维指针表示二维数组,动态分配内存空间
KeyNode **bucket_num = (KeyNode **)malloc(bucket_size * sizeof(KeyNode*)); //分配行所用的空间
for(i = 0;i < bucket_size;i++) {
bucket_num[i] = (KeyNode*)malloc(sizeof(KeyNode)); //为每个桶分配内存空间,分配列所用的空间
bucket_num[i]->num = 0; //记录当前桶中的数量,初始化桶中数量为0
bucket_num[i]->next = NULL; //为结构体中的结构体指针变量初始化为空
}
for(j = 0;j < size;j++) {
KeyNode *node = (KeyNode *)malloc(sizeof(KeyNode)); //定义一个结构体变量的指针
node->num = a[j];
node->next = NULL;
int index = a[j]/100; //映射函数计算桶号
KeyNode *p = bucket_num[index]; //初始化P成为桶中数据链条的头指针
//该桶中还没有数据
if(p->num == 0)
{
bucket_num[index]->next = node;
(bucket_num[index]->num)++;
}else
{
//链表结构的插入排序
while(p->next != NULL && p->next->num <= node->num)
{
p = p->next;
}
node->next = p->next;
p->next = node;
(bucket_num[index]->num)++;
}
}
//打印结果
KeyNode * k = NULL; //定义一个空的结构体指针用于储存输出结果
for(i = 0;i < bucket_size;i++)
{
for(k = bucket_num[i]->next;k!=NULL;k=k->next)
{
printf("%d ",k->num);
}
}
printf("\n");
}
int main()
{
int a[] {491,381,615,917,716,13,217,419,19,138,61,917,176,113,27,419,419,38,615,917,16,113,217,419};
int size = sizeof(a)/sizeof(int); //计算数组长度
bucket_sort(a,size,10);
system("pause"); //防止控制台闪退
}