浅显易懂的桶排序

想准备将所有的排序算法都总结出来,方便你查阅,也方便我复习和记忆,下面来说桶排序:

首先必须申明,桶排序和计数排序完全不同,不可混为一谈:(这里实例用单链表来操作)

还是老方法,看文字就是烦,直接上图,图文结合,永远都是王道:

1.假设:桶待排序列:{ 49, 38, 35, 97, 76, 73, 27, 49 ,34,78}

看了之后有没有特莫感觉就是哈希桶,哈哈,满足一定条件差不多就是啦;言归正传,key值就是待排序序列,Bucket为桶,数据按某种函数,映射到桶中

2.关于映射及桶排原理分析:

  桶中数据的十位都一样,那么映射函数算出的桶号就是这些数据的十位,也就是说,这种映射函数,目的就是为了找出数据的共同特点,可能是求余(哈希表直接定址,就是这样),可能是除某数求商,本例中就是取商;

即就是所有数据除某数取得的商相同的都放一个桶中,如图中的3号桶,刚开始,3号桶中的数据是无序的,第一遍操作,只能保证这些数据一定是在这个桶中,

但是桶中的顺序还是要排的,之后,遍历一遍桶,输出即就是一个有序序列,就这几句话,我感觉说完了,至于更深层 的剖析,稍后再说,先来代码:

#pragma once

//每一个节点的结构
struct node
{
	int key;  //关键字,在桶中统计桶中数据量,在数据节点中就是节点的数据
	struct node *next;
};

//声明:
void PrintBucketSort(node** bucket, int bucket_size);
int f(int x);

void BucketSort(int* a, int size,int bucket_size)
{
	assert(a);
	
	//给桶申请空间
	node** bucket = new node*[bucket_size*sizeof(node)]; 

	//初始化
	for (int i = 0; i < bucket_size; ++i)
	{
		bucket[i] = new node[sizeof(node)]; //每一个桶
		bucket[i]->key = 0;
		bucket[i]->next = nullptr;
	}

	for (int j = 0; j < size; ++j)
	{
		node* sub_node = new node[sizeof(node)]; //桶下的每一个节点
		sub_node->key = a[j];
		sub_node->next = nullptr;

		//计算这数据在哪个桶中
		int num = f(a[j]);

		//让一个指针指向这个桶号的头
		node* sub_head = bucket[num];

		//开始插入
		if (sub_head->next == nullptr)
		{
			bucket[num]->next = sub_node;
			bucket[num]->key++;
		}
		//该桶号不为空,那么插入排序
		else
		{
			while (sub_head->next != nullptr && sub_node->key >= sub_head->next->key)
			{
				sub_head = sub_head->next;
			}

			sub_node->next = sub_head->next;
			sub_head->next = sub_node;
			bucket[num]->key++;
		}
	}
	//打印
	PrintBucketSort(bucket, bucket_size);
}

//映射函数
int f(int x)
{
	return (x / 10);
}

//打印
void PrintBucketSort(node** bucket, int bucket_size)
{
	//多少桶链(桶号)
	for (int i = 0; i < bucket_size; ++i)
	{
		node* cur = bucket[i]->next;
		while (cur)
		{
			cout << cur->key << " ";
			cur = cur->next;
		}
	}
	cout << endl;
}

void Test7()
{
	int a[10] = { 49, 38, 35, 97, 76, 73, 27, 49, 34, 78 };
	cout << "桶排序" << endl;
	BucketSort(a, 10, 10);  //桶数据最大才97,所以需要10个桶
}
哎呀,敲了我十几分钟,看看结果:

第一个就是排序,第二个就是数据在桶中的分布,横行代表桶,10个桶,没有数据的桶是0;

桶排序就是这样:

对于N个待排数据,M个桶,平均每个桶[N/M]个数据的桶排序平均时间复杂度为:


             O(N)+O(M*(N/M)*log(N/M))=O(N+N*(logN-logM))=O(N+N*logN-N*logM)


当N=M时,即极限情况下每个桶只有一个数据时。桶排序的最好效率能够达到O(N)
 
桶排序的平均时间复杂度为线性的O(N+C),其中C=N*(logN-logM)。如果相对于同样的N,桶数量M越大,其效率越高,最好的时间复杂度达到O(N)。 

当然桶排序的空间复杂度 为O(N+M),如果输入数据非常庞大,而桶的数量也非常多,则空间代价无疑是昂贵的。

此外,桶排序是稳定的。

赐教!

posted @ 2016-05-11 12:06  云端止水  阅读(809)  评论(0编辑  收藏  举报