桶排序

桶排序

桶排序(Bucket Sort)是对基数排序的一个变种。在排序过程中没有用到计数数组,而是用不同的桶来暂时存储关键字。看一个示意图:

排序序列 123 234 45 111 6 128


整个过程就是在不断地分配、收集。并且每一个桶都是队列,所以收集的时候得按先进先出的原则,且从第0个桶开始收集。

在实际应用中,根据桶的创建策略,桶排序也有不同的写法。下面给出两种不同的桶创建方式。一、使用静态队列创建桶。二、使用二维数组模拟桶。

静态队列桶

#include<iostream>
#include<iomanip>
using namespace std;
//记录类型
typedef struct record
{
	int key;
	int next;
}Record;
//静态队列
typedef struct queue
{
	//队头
	int head;
	//队尾
	int tail;
}StaticQueue;
//获取最大位数
int get_max_digit(int array[], int n)
{
	int digit, max;
	digit = 0;
	max = array[0];
	for (int i = 1; i < n; i++)
	{
		if (array[i] > max)
			max = array[i];
	}
	while (max)
	{
		digit++;
		max /= 10;
	}
	return digit;
}

/*
收集
把10个桶连接起来
*/
void collect(Record rec[], StaticQueue queue[], int& first)
{
	//k是桶号
	int tail, k = 0;
	//先找到第一个非空的桶
	while (queue[k].head == -1)
		k++;
	//用first记录第一个记录的位置,为下次分配使用
	first = queue[k].head;
	tail = queue[k].tail;
	while (k < 9)
	{
		k++;
		while (k < 9 && queue[k].head == -1)
			k++;
		//把上一个桶的尾部和当前桶的头部连接起来
		if (queue[k].head != -1)
		{
			rec[tail].next = queue[k].head;
			tail = queue[k].tail;
		}
	}
	rec[tail].next = -1;
}

/*
分配
把n个记录分配到10个桶中
r:从右数按第r位排序(r=1,2...)
first:第一个记录的下标
*/
void distribute(Record rec[], int r, int first, StaticQueue queue[])
{
	//先把队列初始化
	int i, d, cur = first;
	for (i = 0; i < 10; i++)
		queue[i].head = -1;

	i =  d = 1;
	while (i < r)
	{
		i++;
		d *= 10;
	}
	int k;
	//把记录分配每一个桶中
	while (cur != -1)
	{
		k = (rec[cur].key / d) % 10;
		//桶空,则当前记录是第一个
		if (queue[k].head == -1)
			queue[k].head = cur;
		else//桶非空,则当前记录连接到尾部
			rec[queue[k].tail].next = cur;
		//修改队列尾部,这一句不可忘了
		queue[k].tail = cur;
		//继续给下一个记录分桶
		cur = rec[cur].next;
	}
}

/*
重排
first:第一个记录的下标
*/
void arrange(Record rec[], int n, int first)
{
	int i, j = first;
	Record temp;
	for (i = 0; i < n - 1; i++)
	{
		temp = rec[j];
		rec[j] = rec[i];
		rec[i] = temp;
		rec[i].next = j;
		j = temp.next;
		while (j <= i)
			j = rec[j].next;
	}
}

/*
基数排序
array:待排序序列
n:序列大小
*/
void RadixSort(int array[], int n)
{
	//对排序序列进行封装
	int i;
	Record *rec = new Record[n];
	for (i = 0; i < n; i++)
	{
		rec[i].key = array[i];
		rec[i].next = i + 1;
	}
	rec[n - 1].next = -1;
	/*
	创建静态队列,每一个队列相当于一个桶
	对于十进制数,只需10个桶即可
	*/
	StaticQueue queue[10];
	//获取最大排序位数
	int digit = get_max_digit(array, n);
	int first = 0;
	for (i = 1; i <= digit; i++)
	{
		distribute(rec, i, first, queue);
		collect(rec, queue, first);
	}
	//重排
	arrange(rec, n, first);
	//回放
	for (i = 0; i < n; i++)
		array[i] = rec[i].key;
	//释放空间
	delete[]rec;
}

//打印
void print(int array[], int n)
{
	for (int i = 0; i < n; i++)
		cout << setw(6) << array[i];
	cout << endl;
}

int main()
{
	cout << "******桶排序(静态队列)***by David***" << endl;
	int array[] = { 123, 234, 45, 111, 6, 128 };
	int n = sizeof(array) / sizeof(int);
	cout << "原序列" << endl;
	print(array, n);
	cout << "桶排序" << endl;
	RadixSort(array, n);
	print(array, n);
	system("pause");
	return 0;
}

运行

桶排序_第1张图片


代码下载:桶排序(静态队列)

二维数组桶  

#include<iostream>
#include<iomanip>
using namespace std;
//最大排序个数
const int N = 12;
//分配
void distribute(int array[], int n, int bucket[][N+1], int r)
{
	int i;
	//对桶进行初始化,bucket[i][0]存放的是第i个桶中元素个数
	for (i = 0; i < 10; i++)
		bucket[i][0] = 0;
	int d;
	i = d = 1;
	while (i < r)
	{
		d *= 10;
		i++;
	}
	int k;
	for (i = 0; i < n; i++)
	{
		k = (array[i] / d) % 10;
		bucket[k][0]++;
		bucket[k][bucket[k][0]] = array[i];
	}
}
//收集
void collect(int array[], int n, int bucket[][N+1])
{
	int i, j, index;
	index = 0;
	for (i = 0; i < 10; i++)
	for (j = 1; j <= bucket[i][0]; j++)
		array[index++] = bucket[i][j];
}
//获取最大位数
int get_max_digit(int array[], int n)
{
	int digit, max;
	digit = 0;
	max = array[0];
	for (int i = 1; i < n; i++)
	{
		if (array[i] > max)
			max = array[i];
	}
	while (max)
	{
		digit++;
		max /= 10;
	}
	return digit;
}
//桶排序
void BucketSort(int array[], int n)
{
	int digit = get_max_digit(array, n);
	int i;
	int bucket[10][N+1];
	for (i = 1; i <= digit; i++)
	{
		//分配
		distribute(array, n, bucket, i);
		//收集
		collect(array, n, bucket);
	}
}
//打印
void print(int *a, int n)
{
	for (int i = 0; i < n; i++)
		cout << setw(6) << a[i];
	cout << endl;
}
int main()
{
	cout << "******桶排序(二维数组)***by David***" << endl;
	int array[] = { 123, 234, 45, 111, 6, 128 };
	int n = sizeof(array) / sizeof(int);
	cout << "原序列" << endl;
	print(array, n);
	cout << "桶排序" << endl;
	BucketSort(array, n);
	print(array, n);
	system("pause");
	return 0;
}

运行

桶排序_第2张图片


代码下载:桶排序(二维数组)


小结

上面的两种方式都是桶排序的具体实现,总体上是分配和收集的过程。不过细节很多,需要仔细看代码。


转载请注明出处,本文地址:http://blog.csdn.net/zhangxiangdavaid/article/details/37668921


若有所帮助,顶一个哦!


专栏目录:

  • 数据结构与算法目录
  • c指针


你可能感兴趣的:(数据结构,二维数组,存储,桶排序,静态链表)