桶排序(C语言)

桶排序是计数排序的升级版。它利用了函数的映射关系,高效与否的关键就在于这个映射函数的确定。为了使桶排序更加高效,我们需要做到这两点:

  • 在额外空间充足的情况下,尽量增大桶的数量
  • 使用的映射函数能够将输入的 N 个数据均匀的分配到 K 个桶中

示意图

image

然后,元素在每个桶中排序:


image
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <time.h>

//交换数值
void swap(int *a,int *b)
{
    int temp = *a;
    *a = *b;
    *b = temp;
}
//打印数组
void printArray(char msg[],int arr[],int len){
    printf("%s:",msg);
    for (int i = 0; i < len; i++){
        printf("%d ", arr[i]);
    }
    printf("\n");
}
//链表节点
struct bucketitem{
    int index;
    int data;
    struct bucketitem* next;
};
//桶排序
void bucket_sort(int a[],int len){
    int maxvalue=a[0],minvalue=a[0];
    for(int x=0;x<len;x++){
        maxvalue=a[x]>maxvalue?a[x]:maxvalue;
        minvalue=a[x]<minvalue?a[x]:minvalue;
    }
    //获取每个桶容量
    int bucketsize=(maxvalue-minvalue)/len+1;
    //获取桶数量
    int bucketcount=(maxvalue-minvalue)/bucketsize+1;
    struct bucketitem buckets[bucketcount];
    //初始化链表头
    for(int i=0;i<bucketcount;i++){
        struct bucketitem item={-1,0,NULL};
        //每个桶链表的表头不存数据,统一设置为标识表头
        buckets[i]=item;
    }
    //放置临时分配的内存地址
    int m[len];
    for(int i=0;i<len;i++){
        //算出a[i]对应的桶位置
        int pos=(a[i]-minvalue)/bucketsize;
        //新建链表节点并赋值
        struct bucketitem* item=(struct bucketitem*) malloc(sizeof(struct bucketitem));
        item->index=i;
        item->data=a[i];
        item->next=NULL;
        //将新节点推入pos位置链表
        link_push(&buckets[pos],item);
        m[i]=item;
    }
    print_range(a,len,buckets);
    int k=0;
    //从小到大遍历桶位置,并把桶中排序好的元素取出赋值给a数组
    for(int i=0;i<bucketcount;i++){
        struct bucketitem* cur=buckets[i].next;
        while(cur!=NULL){
            a[k++]=cur->data;
            cur=cur->next;
        }
    }
    //释放内存
    for(int i=0;i<len;i++){
        free(m[i]);
    }
}
//推入链表合适位置
void link_push(struct bucketitem* src,struct bucketitem* item){
    struct bucketitem* pre=src;
    struct bucketitem* cur=src->next;
    //遍历链表找到cur->data>item->data的位置
    while(cur!=NULL&&cur->data<=item->data){
        pre=cur;
        cur=cur->next;
    }
    //插入节点item,改变item节点next指向cur
    pre->next=item;
    item->next=cur;
}
//打印调试信息
void print_range(int a[],int len,struct bucketitem buckets[]){
    int maxval=a[0],minval=a[0];
    for(int x=0;x<len;x++){
        maxval=a[x]>maxval?a[x]:maxval;
        minval=a[x]<minval?a[x]:minval;
    }
    int s = (maxval-minval)/len+1;
    printf("size:%d\n",s);
    int c = (maxval-minval)/s+1;
    printf("count:%d\n",c);
    for(int i=0;i<c;i++){
        printf("index:%d,[%d,%d):",i,minval+i*s,minval+(i+1)*s);
        struct bucketitem* cur=buckets[i].next;
        while(cur!=NULL){
            printf("%d ",cur->data);
            cur=cur->next;
        }
        printf("\n");
    }
}

int main()
{
    int len=256;
    int arr[len];
    srand((unsigned)time(NULL));
    //随机生成长度为"len"的数组
    for(int i=0;i<len;i++){
        arr[i]=rand()%256;
    }
    printArray("未排序前",arr,len);
    printf("\n");
    bucket_sort(arr,len);
    printf("\n");
    printArray("在排序后",arr,len);
    //防止windows下控制台窗口闪退
    int s;
    scanf("%d",&s);
    return 0;
}

运行结果:

未排序前:18 41 60 63 58 165 92 82 127 111
size:15
count:10
index:0,[18,33):18
index:1,[33,48):41
index:2,[48,63):58 60
index:3,[63,78):63
index:4,[78,93):82 92
index:5,[93,108):
index:6,[108,123):111
index:7,[123,138):127
index:8,[138,153):
index:9,[153,168):165
桶排序::18 41 58 60 63 82 92 111 127 165

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容