桶排序 (Bucket sort)或所谓的箱排序,是一个排序算法,工作的原理是将数组分到有限数量的桶子里。每个桶子再个别排序(有可能再使用别的排序算法或是以递归方式继续使用桶排序进行排序)。桶排序是鸽巢排序的一种归纳结果。当要被排序的数组内的数值是均匀分配的时候,桶排序使用线性时间(Θ(n))。但桶排序并不是 比较排序,他不受到 O(n log n) 下限的影响。
算法描述:
设置一个定量的数组当作空桶;
遍历输入数据,并且把数据一个一个放到对应的桶里去;
对每个不是空的桶进行排序;
从不是空的桶里把排好序的数据拼接起来。
算法分析
桶排序最好情况下使用线性时间O(n),桶排序的时间复杂度,取决与对各个桶之间数据进行排序的时间复杂度,因为其它部分的时间复杂度都为O(n)。很显然,桶划分的越小,各个桶之间的数据越少,排序所用的时间也会越少。但相应的空间消耗就会增大。
假如我们给出一组数据,即29, 25, 3, 49, 9, 37 ,21 ,43。
那么我们可以这样来进行排序。假如我们给出的数是在0到100之间。
实现过程:
#include <stdio.h>
#include<stdlib.h>
// 桶的个数
#define BucketNumber 100
// 桶元素结点
typedef int ElemType;
struct Node {
ElemType key;//值
struct Node *next;//下一个指针
};
typedef Node * ptr2Node;
// 桶头结点
struct Bucket {
ptr2Node head, tail;//头,尾
};
桶排序的核心思想
void BucketSort(ElemType A[], int N) {
int i;
ptr2Node tmp, p, List = NULL;
Bucket B[BucketNumber];//数组大小为100,每个数组里面含有指向结点的头尾指针。
for (i = 0; i < BucketNumber; i++) // 初始化每个桶为空链表
B[i].head = B[i].tail = NULL;
for (i = 0; i < N; i++) { // 将原始序列逆序存入初始链表List
tmp = (ptr2Node)malloc(sizeof(struct Node));
tmp->key = A[i];
tmp->next = List;
List = tmp;
}
// 分配
p = List;
while (p) {
// 从List中摘除
tmp = p; p = p->next;
// 插入B[tmp->key]号桶尾
if (B[tmp->key].head == NULL)//如果这个数组还没有元素
B[tmp->key].tail = tmp;//这个数组的尾结点指向这一个元素结点
tmp->next = B[tmp->key].head;//数组为空,则这个元素结点的下一个指向也为空,若这个下标数组已经有值了,那么指向第一个元素结点。
B[tmp->key].head = tmp;//每次更新第一个元素结点。
}
// 收集
List = NULL;
for (i = BucketNumber - 1; i >= 0; i--) // 从小到大排序
if (B[i].head) { // 如果桶不为空
// 整桶插入List表头
B[i].tail->next = List;//连接起来
List = B[i].head;
B[i].head = B[i].tail = NULL; // 清空桶
}
// 将List倒入A[]并释放空间
for (i = 0; i < N; i++) {
tmp = List;
List = List->next;
A[i] = tmp->key;
free(tmp);
}
}
打印函数
void ArrShow(int *a, int length) {
for (int i = 0; i < length; i++) {
printf("%3d",a[i]);
}
printf("\n");
}
主函数
int main() {
int test[9] = { 1, 2, 11, 66, 53, 55, 54, 16, 4 };
ArrShow(test, 9);
puts("BucketSort : ");
BucketSort(test, 9);
ArrShow(test, 9);
return 0;
}
文章总代码
#include <stdio.h>
#include<stdlib.h>
// 桶的个数
#define BucketNumber 100
// 桶元素结点
typedef int ElemType;
struct Node {
ElemType key;
struct Node *next;
};
typedef Node * ptr2Node;
// 桶头结点
struct Bucket {
ptr2Node head, tail;
};
void BucketSort(ElemType A[], int N) {
int i;
ptr2Node tmp, p, List = NULL;
Bucket B[BucketNumber];
for (i = 0; i < BucketNumber; i++) // 初始化每个桶为空链表
B[i].head = B[i].tail = NULL;
for (i = 0; i < N; i++) { // 将原始序列逆序存入初始链表List
tmp = (ptr2Node)malloc(sizeof(struct Node));
tmp->key = A[i];
tmp->next = List;
List = tmp;
}
// 分配
p = List;
while (p) {
// 从List中摘除
tmp = p; p = p->next;
// 插入B[tmp->key]号桶尾
if (B[tmp->key].head == NULL)
B[tmp->key].tail = tmp;
tmp->next = B[tmp->key].head;
B[tmp->key].head = tmp;
}
// 收集
List = NULL;
for (i = BucketNumber - 1; i >= 0; i--) // 从小到大排序
if (B[i].head) { // 如果桶不为空
// 整桶插入List表头
B[i].tail->next = List;
List = B[i].head;
B[i].head = B[i].tail = NULL; // 清空桶
}
// 将List倒入A[]并释放空间
for (i = 0; i < N; i++) {
tmp = List;
List = List->next;
A[i] = tmp->key;
free(tmp);
}
}
void ArrShow(int *a, int length) {
for (int i = 0; i < length; i++) {
printf("%3d",a[i]);
}
printf("\n");
}
int main() {
int test[9] = { 1, 2, 11, 66, 53, 55, 54, 16, 4 };
ArrShow(test, 9);
puts("BucketSort : ");
BucketSort(test, 9);
ArrShow(test, 9);
return 0;
}