桶排序(Bucket Sort)

基本思想

假设有一组长度为N的待排关键字序列K[1....n]。首先将这个序列划分成M个的子区间(桶) 。然后基于某种映射函数 ,将待排序列的关键字k映射到第i个桶中(即桶数组B的下标 i) ,那么该关键字k就作为B[i]中的元素(每个桶B[i]都是一组大小为N/M的序列)。接着对每个桶B[i]中的所有元素进行比较排序(可以使用快排)。然后依次枚举输出B[0]....B[M]中的全部内容即是一个有序序列。

映射函数

 bindex=f(key)   其中,bindex 为桶数组B的下标(即第bindex个桶), k为待排序列的关键字。桶排序之所以能够高效,其关键在于这个映射函数,它必须做到:如果关键字k1<k2,那么f(k1)<=f(k2)。也就是说B(i)中的最小数据都要大于B(i-1)中最大数据。很显然,映射函数的确定与数据本身的特点有很大的关系,我们下面举个例子:

 

假如待排序列K= {49、 38 、 35、 97 、 76、 73 、 27、 49 }。这些数据全部在1—100之间。因此我们定制10个桶,然后确定映射函数f(k)=k/10。则第一个关键字49将定位到第4个桶中(49/10=4)。依次将所有关键字全部堆入桶中,并在每个非空的桶中进行快速排序后得到如下图所示:

                                                       

对上图只要顺序输出每个B[i]中的数据就可以得到有序序列了。

示例代码

#include<iostream>
using namespace std;
//约定所有数据都是在0-100的自然数
int data[30]={49,48,35,97,76,3,27,59,5,6,7,8,9,0,22,33,44,55,66,65,78,11,23,24,25,26,27,28,29,30};

typedef struct BucketSet{
	int key;
	struct BucketSet * next;

};

int myBucketSort(int data[],int length){
	BucketSet  bs[10];
	for(int i=0;i<10;i++){
		bs[i].key=i;
		bs[i].next=0;	
	}
	for(int i=0;i<length;i++){
		BucketSet *nextBS=(BucketSet *)malloc(sizeof(BucketSet));
		nextBS->key=data[i];
		//入桶
		BucketSet *temp=&bs[data[i]/10];
		BucketSet *tempNext=temp->next;
		while(tempNext && tempNext->key<nextBS->key){
			temp=temp->next;
			tempNext=temp->next;
		}
		temp->next=nextBS;
		nextBS->next=tempNext;
		
	}
	//排序
	int j=0;
	for(int i=0;i<10;i++){
		BucketSet *temp=bs[i].next;
		while(temp){
			data[j++]=temp->key;
			temp=temp->next;
		}
		
	}

return 0;
}


int main(){
	myBucketSort(data,30);
	for(int i=0;i<30;i++)
		cout<<data[i]<<" ";
	getchar();

	return 0;
}

  

posted on 2014-03-27 16:08  兵临天下  阅读(335)  评论(0)    收藏  举报

导航