桶排序 (Bucket sort)或所谓的箱排序,是一个排序算法,工作的原理是将数组分到有限数量的桶子里。每个桶子再个别排序(有可能再使用别的排序算法或是以递归方式继续使用桶排序进行排序)。桶排序是鸽巢排序的一种归纳结果。当要被排序的数组内的数值是均匀分配的时候,桶排序使用线性时间(Θ(n))。但桶排序并不是 比较排序,他不受到 O(n log n) 下限的影响。
-
中文名
- 桶排序 要 求
- 数据的长度必须完全一样 公 式
- Data=rand()/10000+10000
-
数据结构设计
- 链表可以采用很多种方式实现 性 质
- 平均情况下桶排序以线性时间运行 原 理
- 桶排序利用函数的映射关系 领 域
- 计算机算法
假定:输入是由一个随机过程产生的[0, 1)区间上均匀分布的实数。将区间[0, 1)划分为n个大小相等的子区间(桶),每桶大小1/n:[0, 1/n), [1/n, 2/n), [2/n, 3/n),…,[k/n, (k+1)/n ),…将n个输入元素分配到这些桶中,对桶中元素进行排序,然后依次连接桶输入0 ≤A[1..n] <1辅助数组B[0..n-1]是一指针数组,指向桶(链表)。
数据结构设计:链表可以采用很多种方式实现,通常的方法是动态申请内存建立结点,但是针对这个算法,桶里面的链表结果每次扫描后都不同,就有很多链表的分离和重建。如果使用动态分配内存,则由于指针的使用,安全性低。所以,笔者设计时使用了数组来模拟链表(当然牺牲了部分的空间,但是操作却是简单了很多,稳定性也大大提高了)。共十个桶,所以建立一个二维数组,行向量的下标0—9代表了10个桶,每个行形成的一维数组则是桶的空间。
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
|
#include<iostream>
usingnamespace std;
int
a[]={1,255,8,6,25,47,14,35,58,75,96,158,657};
const
int
len=
sizeof
(a)/
sizeof
(
int
);
int
b[10][len+1]={0};
//将b全部置0
void
bucketSort(
int
a[]);
//桶排序函数
void
distribute Elments(
int
a[],
int
b[10][len+1],
int
digits);
void
collectElments(
int
a[],
int
b[10][len+1]);
int
numOfDigits(
int
a[]);
void
zeroBucket(
int
b[10][len+1]);
//将b数组中的全部元素置0
int
main()
{
cout<<
"原始数组:"
;
for
(
int
i=0;i<len;i++)
cout<<a[i]<<
","
;
cout<<endl;
bucketSort(a);
cout<<
"排序后数组:"
;
for
(
int
i=0;i<len;i++)
cout<<a[i]<<
","
;
cout<<endl;
return
0;
}
void
bucketSort(
int
a[])
{
int
digits=numOfDigits(a);
for
(
int
i=1;i<=digits;i++)
{
distributeElments(a,b,i);
collectElments(a,b);
if
(i!=digits)
zeroBucket(b);
}
}
int
numOfDigits(
int
a[])
{
int
largest=0;
for
(
int
i=0;i<len;i++)
//获取最大值
if
(a[i]>largest)
largest=a[i];
int
digits=0;
//digits为最大值的位数
while
(largest)
{
digits++;
largest/=10;
}
return
digits;
}
void
distributeElments(
int
a[],
int
b[10][len+1],
int
digits)
{
int
divisor=10;
//除数
for
(
int
i=1;i<digits;i++)
divisor*=10;
for
(
int
j=0;j<len;j++)
{
int
numOfDigist=(a[j]%divisor-a[j]%(divisor/10))/(divisor/10);
//numOfDigits为相应的(divisor/10)位的值,如当divisor=10时,求的是个位数
int
num=++b[numOfDigist][0];
//用b中第一列的元素来储存每行中元素的个数
b[numOfDigist][num]=a[j];
}
}
void
collectElments(
int
a[],
int
b[10][len+1])
{
int
k=0;
for
(
int
i=0;i<10;i++)
for
(
int
j=1;j<=b[i][0];j++)
a[k++]=b[i][j];
}
void
zeroBucket(
int
b[][len+1])
{
for
(
int
i=0;i<10;i++)
for
(
int
j=0;j<len+1;j++)
b[i][j]=0;
}
|
JAVA
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
public
static
void
basket(
int
data[])
//data为待排序数组
{
int
n=data.length;
int
bask[][]=
new
int
[
10
][n];
int
index[]=
new
int
[
10
];
int
max=Integer.MIN_VALUE;
for
(
int
i=
0
;i<n;i++)
{
max=max>(Integer.toString(data[i]).length())?max:(Integer.toString(data[i]).length());
}
String str;
for
(
int
i=max-
1
;i>=
0
;i--)
{
for
(
int
j=
0
;j<n;j++)
{
str=
""
;
if
(Integer.toString(data[j]).length()<max)
{
for
(
int
k=
0
;k<max-Integer.toString(data[j]).length();k++)
str+=
"0"
;
}
str+=Integer.toString(data[j]);
bask[str.charAt(i)-
'0'
][index[str.charAt(i)-
'0'
]++]=data[j];
}
int
pos=
0
;
for
(
int
j=
0
;j<
10
;j++)
{
for
(
int
k=
0
;k<index[j];k++)
{
data[pos++]=bask[j][k];
}
}
for
(intx=
0
;x<
10
;x++)index[x]=
0
;
}
}
|
桶排序有其局限性,适合元素值集合并不大的情况。‘
以上实现复杂,目前竞赛只用到一维数组的桶排序,复杂度O(M+N),M为桶数,N为元素个数(见啊哈算法)