桶排序是另外一种以O(n)或者接近O(n)的复杂度排序的算法. 它假设输入的待排序元素是等可能的落在等间隔的值区间内.一个长度为N的数组使用桶排序, 需要长度为N的辅助数组. 等间隔的区间称为桶, 每个桶内落在该区间的元素. 桶排序是基数排序的一种归纳结果
算法的主要思想: 待排序数组A[1...n]内的元素是随机分布在[0,1)区间内的的浮点数.辅助排序数组B[0....n-1]的每一个元素都连接一个链表.将A内每个元素乘以N(数组规模)取底,并以此为索引插入(插入排序)数组B的对应位置的连表中. 最后将所有的链表依次连接起来就是排序结果.
这个过程可以简单的分步如下:
- 设置一个定量的数组当作空桶子。
- 寻访序列,并且把项目一个一个放到对应的桶子去。
- 对每个不是空的桶子进行排序。
- 从不是空的桶子里把项目再放回原来的序列中。
note: 待排序元素越均匀, 桶排序的效率越高. 均匀意味着每个桶在中间过程中容纳的元素个数都差不多,不会出现特别少或者特别多的情况, 这样在排序子程序进行桶内排序的过程中会达到最优效率.
note: 将元素通过恰当的映射关系将元素尽量等数量的分到各个桶(值区间)里面, 这个映射关系就是桶排序算法的关键.桶的标记(数组索引Index)的大小也要和值区间有对应关系。
以下是一段桶排序的源码:
#include <stdio.h> #include <stdlib.h> #include <string.h> extern void quick_sort(int a[], int p, int q);/* not necessary */ struct barrel { int node[10]; int count;/* the num of node */ }; void bucket_sort(int data[], int size) { int max, min, num, pos; int i, j, k; struct barrel *pBarrel; max = min = data[0]; for (i = 1; i < size; i++) { if (data[i] > max) { max = data[i]; } else if (data[i] < min) { min = data[i]; } } num = (max - min + 1) / 10 + 1; pBarrel = (struct barrel*)malloc(sizeof(struct barrel) * num); memset(pBarrel, 0, sizeof(struct barrel) * num); /* put data[i] into barrel which it belong to */ for (i = 0; i < size; i++) { k = (data[i] - min + 1) / 10;/* calculate the index of data[i] in barrel */ (pBarrel + k)->node[(pBarrel + k)->count] = data[i]; (pBarrel + k)->count++; } pos = 0; for (i = 0; i < num; i++) { quick_sort((pBarrel+i)->node, 0, (pBarrel+i)->count);/* sort node in every barrel */ for (j = 0; j < (pBarrel+i)->count; j++) { data[pos++] = (pBarrel+i)->node[j]; } } free(pBarrel); } main() { int data[] = {78, 17, 39, 26, 72, 94, 21, 12, 23, 91}, i; int size = sizeof(data) / sizeof(int); bucket_sort(data, size); for (i = 0; i < size; i++) printf("%d ", data[i]); }