算法理解:
桶排序是对计数排序的一种优化,在计数排序中x应该放在计数数组下表为x的位置上,这样如果重复数字较少,计数数组每个位置的利用率就非常小。
桶排序是将一系列大小近似的数字放在一个位置(每个桶维护一条有序的链表),这样提高每个位置的利用率,以提高效率.
以A【】={1,21,23,41,49}为例
假设每个桶里有10中元素,那么桶排序的结构如下图所示。

#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
#include <cstdio>
#include <cmath>
#include <queue>
using namespace std;
const int maxn=1e5+10;
typedef struct node{
int key;
struct node* next;
}KeyNode;
void bucket_sort(int keys[],int size,int bucket_size){
KeyNode **bucket_table=(KeyNode**)malloc(bucket_size*sizeof(KeyNode*));
for(int i=0;i<bucket_size;i++){ //初始化桶
bucket_table[i]=(KeyNode*)malloc(sizeof(KeyNode));
bucket_table[i]->key=0;
bucket_table[i]->next=NULL;
}
for(int i=0;i<size;i++){
KeyNode* node=(KeyNode*)malloc(sizeof(KeyNode));
node->key=keys[i];
node->next=NULL;
int index=keys[i]/10;//给数据分类的方法(关系到排序速度,很重要)
KeyNode *p=bucket_table[index];
if(p->key==0){
p->next=node;
p->key++;
}
else{
while(p->next!=NULL&&p->next->key<=node->key){//=的时候后来的元素会排在后面
p=p->next;
}
node->next=p->next;
p->next=node;
(bucket_table[index]->key)++;
}
}
KeyNode* k=NULL;
for(int i=0;i<bucket_size;i++){
for(k=bucket_table[i]->next;k!=NULL;k=k->next){
printf("%d ",k->key);
}
}
}
int main(){
int n;int a[maxn];
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
}
bucket_sort(a,n,100);
return 0;
}
例一:
给你一个数组,找到差值绝对值最小是多少?
解:最简单的思路就是先排序,之后遍历一遍,时间复杂度是O(nlogn),那么能否O(n)求解呢,是可以的。
如果有n个数,那么我们把最大到最小值之间的数字分到n-1个桶里,必然会有两个数字在一个桶里(鸽巢原理)(抽屉原理),最小值值可能是这个桶的最小值和上一个桶的最大值的差,或者两个在同个桶的数字,对于不同的桶我们遍历一遍,对于相同的桶又回到了最初的问题,即给你一个数组,找到差值绝对值最小是多少?,这样相同的桶就递归处理,即可使效率达到比较高的状态。