您的位置:首页 > 其它

桶排序(Bucket Sort)

2017-01-17 12:48 369 查看

桶排序(Bucket Sort)

桶排序Bucket Sort
基本思想

排序流程

算法实现

算法分析

1. 基本思想

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

步骤

划分桶

入桶

桶内排序

出桶

2. 排序流程

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

首先,可以把桶设为大小为10的范围,具体而言,设集合B[1]存储[0, 10)的整数,集合B[2]存储[10, 20)的整数,……集合B[i]存储[(i−1)∗10,i∗10)的整数,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
={11, 23, 17, 35, 6, 19, 24, 1, 30, 29, 7, 11, 22};

int bucket[NBUCKET]
={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;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[
4000
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");
}


[b]结果


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+m∗n/m∗log(n/m))=O(n+nlogn−nlogm)

当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)其次待排序的元素都要在一定的范围内等等。

桶式排序是一种分配排序。分配排序的特定是不需要进行关键码的比较,但前提是要知道待排序列的一些具体情况。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  算法 排序