(七)基数排序

基数排序

1、思想与概念

    基数排序(radix sort)是一种用在卡片排序机上的算法。基数排序是先按最低有效位进行排序来解决卡片排序问题的。然后算法将所有卡片合并成一叠,其中0号容器中的卡片都在1号容器中的卡片之前,而1号容器中的卡片又在2号容器中的卡片前面,以此类推。之后,用同样的方法按次低有效位对所有的卡片进行排序,并把拍好的卡片再次合并成一叠。重复这一过程,直到对所有的d位数字都进行了排序。此时,所有卡片已按d位数完全排好序。对这一叠卡片的排序仅需要进行d轮。

    为了确保基数排序的正确性,一位数排序算法必须是稳定的。卡片排序机所执行的排序是稳定的,但操作员必须确保卡片从容器中被取出时不改变顺序,即使一个容器中的所有卡片在该位都是相同的数字也要确保这一点。


2、算法思路

    由于基数排序要确保稳定性,所以可以利用计数排序的思想进行对数组元素进行排序。

    基数排序中假设n个d位的元素存放在数组A中,其中第1位是最低位,第n位是最高位。

RADIX-SORT(A,d)
1	for i=1 to d
2	  use a stable sort to sort array A on digit i

3、具体实现

/*基数排序*/
#include <iostream>
using namespace std;

#define M 10//每一位数都是0--9,共10个数

//打印数组
void PrintRadixSort(int *arr, int len)
{
	for (int i = 0; i < len; i++)
	{
		cout << arr[i] << " ";
	}
	cout << endl;
}

//获取数组最大值
int GetMax(int *arr, int len)
{
	int tmp = 0;
	for (int i = 0; i < len; i++)
	{
		if (tmp < arr[i])
		{
			tmp = arr[i];
		}
	}
	return tmp;
}

//计数排序
void CountSort(int *arr, int len, int d)//d代表位数(个十百...)
{
	int *b, *c;
	b = (int*)malloc(sizeof(int)*len);//存放排序结果
	c = (int*)malloc(sizeof(int)*M);//辅助数组
	cout << "\nd=" << d << endl;
	//将辅助数组置为0
	for (int i = 0; i < M; i++)
	{
		c[i] = 0;
	}
	//记录数组arr中每个元素的个数
	for (int i = 0; i < len; i++)
	{
		c[(arr[i] / d) % 10]++;
	}
	cout << "C记录数组arr中每个元素的个数:" << endl;
	PrintRadixSort(c, M);
	//记录数组arr中比前一个元素大或相等的元素个数
	for (int i = 1; i < M; i++)
	{
		c[i] = c[i] + c[i - 1];
	}
	cout << "C记录数组arr中比前一个元素大或相等的元素个数:" << endl;
	PrintRadixSort(c, M);
	//将数组arr中的元素按顺序放入b中
	for (int i = len - 1; i >= 0; i--)
	{
		b[c[(arr[i] / d) % 10]-1] = arr[i];
		c[(arr[i] / d) % 10]--;
	}
	//重新将数组b赋给arr
	for (int i = 0; i < len; i++)
	{
		arr[i] = b[i];
	}
	cout << "arr数组排序后元素顺序:" << endl;
	PrintRadixSort(arr, len);
}

//基数排序
void RadixSort(int *arr, int len)
{
	int max = GetMax(arr, len);
	for (int i = 1; max / i>0; i *= 10)
	{
		CountSort(arr, len, i);
	}
}

int main/*dm010*/()
{
	int len = 0;
	int array[] = { 329, 457, 657, 839, 436, 720, 355 };

	//数组长度
	len = sizeof(array) / sizeof(array[0]);
	//打印数组
	cout << "Before RadixSort array:" << endl;
	PrintRadixSort(array, len);
	//基数排序
	RadixSort(array, len);
	//打印数组
	cout << "\nAfter RadixSort array:" << endl;
	PrintRadixSort(array, len);

	system("pause");
	return 0;
}

4、分析

    引理1:给定n个d位数,其中每一个数位有k个可能的取值。如果RADIX-SORT使用的稳定排序方法耗时O(n+k),那么它就可以在O(d(n+k))时间内将这些数排好序。

    引理2:给定一个d位数和任何正整数r≤b,如果RADIX-SORT使用的稳定排序算法对数据取值区间是0到k的输入进行排序耗时O(n+k),那么它就可以在O((b/r)(n+2r))时间内将这些数排好序。

猜你喜欢

转载自blog.csdn.net/ailunlee/article/details/80231206
今日推荐