桶排序(Bucket Sort)

桶排序是一种非比较型排序算法,将数据分到有限数量的桶里,每个桶再分别排序。它假设输入数据服从均匀分布,通过将数据分到不同的桶内,降低排序的复杂度。算法包括划分桶、入桶、桶内排序和出桶四个步骤,最佳情况下复杂度为O(n)。桶排序是稳定的,并且适用于大规模数据且分布均匀的情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

桶排序(Bucket Sort)


1. 基本思想

简单来说,就是把数据分组,放在一个个的桶中,然后对每个桶里面的再进行排序。

步骤

  1. 划分桶
  2. 入桶
  3. 桶内排序
  4. 出桶

2. 排序流程

例如对[0, 40]范围内的n个整数A[1..n]排序 。

首先,可以把桶设为大小为10的范围,具体而言,设集合B[1]存储[0, 10)的整数,集合B[2]存储[10, 20)的整数,……集合B[i]存储 [(i1)10,i10) 的整数, i=1,2,3,4 ,总共有4个桶。

然后,对A[1..n]从头到尾扫描一遍,把每个A[i]放入对应的桶B[j]中。 再对这4个桶中每个桶里的数字排序,这时可用冒泡,选择,乃至快排,一般来说任何排序法都可以。

最后,依次输出每个桶里面的数字,且每个桶中的数字从小到大输出,这样就得到所有数字排好序的一个序列了。

这里写图片描述

3. 算法实现

代码

#include <stdio.h>

#define N 13
#define NBUCKET 4

int array[N]={11, 23, 17, 35, 6, 19, 24, 1, 30, 29, 7, 11, 22};

int bucket[NBUCKET][N]={0}; /* 以排序0~40间的数为列,分为4个桶[0,10),[10,20),[20,30),[30,40) */
int b_index[NBUCKET]={0}; /* 记录每隔桶中存放的数据个数 */

/* 打印数组 */
void print_array(int arr[],int len)
{
    int i;
    for(i=0;i<N;i++)
        printf("%d ",arr[i]);
    printf("\n");
}

/* 打印桶 */
void print_bucket()
{
    int b,i;
    printf("Buckets num=%d\n",NBUCKET);
    for(b=0;b<NBUCKET;b++) /* 遍历各个桶 */
    {
        printf("Bucket[%d]:\t",b);
        for(i=0;i<b_index[b];i++)
        {
            printf("%d ",bucket[b][i]);
        }
        printf("\n");
    }
}

/* 插入排序 */
void insert_sort(int arr[],int len)
{
    int tmp,i,j;
    for(i=1;i<len;i++)
    {
        if(arr[i]<arr[i-1])
        {
            tmp=arr[i];
            arr[i]=arr[i-1];
            j=i-1;
            while(j>0 && tmp<arr[j-1])  
            {
                arr[j]=arr[j-1];
                j--;
            }
            arr[j]=tmp;
        }
    }
}

/* 冒泡排序 */
void bubble_sort(int arr[],int len)
{
    int i, j, temp;
    for (j = 0; j < len - 1; j++)
    {
        for (i = 0; i < len - 1 - j; i++)
        {
            if(arr[i] > arr[i + 1]) /* 一次判断相邻元素大小,大于则交换 */
            {
                temp = arr[i];
                arr[i] = arr[i + 1];
                arr[i + 1] = temp;
            }
        }
    }
}

/* 桶排序 */
void bucket_sort(int arr[],int len)
{
    int k,b,i;

    for(k=0;k<len;k++) /* 分配数据放各个入桶中 */
    {
        b=arr[k]/10; /* 获取对应的桶 */
        i=b_index[b]; /* 放入桶中的位置 */
        bucket[b][i]=arr[k];
        b_index[b]++; /* 桶中的数据加一 */
    }
    print_bucket();
    for(b=0;b<NBUCKET;b++) /* 各个桶内用插入排序 */
    {
        //bubble_sort(bucket[b],b_index[b]);
        insert_sort(bucket[b],b_index[b]);
    }
    print_bucket();
    k=0;
    for(b=0;b<NBUCKET;b++) /* 遍历各个桶,得到有序序列 */
    {
        for(i=0;i<b_index[b];i++)
        {
            arr[k++]=bucket[b][i];
        }
    }
    print_array(arr,len);
}

void main()
{
    printf("Before...\n");
    print_array(array,N);
    printf("Sorting...\n");
    bucket_sort(array,N);
    printf("Sorted.\n");
}

结果

Before...
11 23 17 35 6 19 24 1 30 29 7 11 22 
Sorting...
Buckets num=4
Bucket[0]:  6 1 7 
Bucket[1]:  11 17 19 11 
Bucket[2]:  23 24 29 22 
Bucket[3]:  35 30 
Buckets num=4
Bucket[0]:  1 6 7 
Bucket[1]:  11 11 17 19 
Bucket[2]:  22 23 24 29 
Bucket[3]:  30 35 
1 6 7 11 11 17 19 22 23 24 29 30 35 
Sorted.

4. 算法分析

  • 时间复杂度

    桶排序采用分配入桶和桶内排序结合的方法,假设有n个数字,有m个桶,如果数字是平均分布的,则每个桶里面平均有n/m个数字。如果对每个桶中的数字采用快速排序,那么整个算法的复杂度是

    O(n+mn/mlog(n/m))=O(n+nlognnlogm)

    当m接近n的时候,桶排序复杂度接近 O(n)

    以上复杂度的计算是基于输入的n个数字是平均分布这个假设的。这个假设是很强的 ,实际应用中效果并没有这么好。如果所有的数字都落在同一个桶中,那就退化成一般的排序了。

    桶排序不是比较排序,不受到 O(nlogn) 下限的影响。

  • 空间复杂度

    由于桶排序需要一个长度为m的桶(m为序列中n个数的范围大小),所以其空间复杂度为 O(m)

  • 稳定性

    桶排序是稳定的。

  • 总结

    大部分时间复杂度都是 O(n2) O(n\log n) O(n)$ 的时间复杂度。桶排序的缺点是:

    (1)首先是空间复杂度比较高,需要的额外开销大。排序有两个数组的空间开销,一个存放待排序数组,一个就是所谓的桶,比如待排序值是从0到m-1,那就需要m个桶,这个桶数组就要至少m个空间。

    (2)其次待排序的元素都要在一定的范围内等等。

    桶式排序是一种分配排序。分配排序的特定是不需要进行关键码的比较,但前提是要知道待排序列的一些具体情况。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值