排序算法(四) 基数排序

本篇博客介绍基于顺序表的实现 LSD,MSD 两种方式

基本思路:看排序数组中最大值的位数,比如说最大值是999,就是三位 K1K2K3,先按K3扫描一遍数组,分别记下K3位为0的个数,为1的个数,……为9的个数,用数组coun[10]来记录,再使用一个数组addr[10]来记录每个桶的起始位置

计算起始地址:addr[idx] = addr[idx-1] + count[idx -1], 再扫描数组根据addr中的起始位置,依次把元素归为。

举个例子:
序列:278,109,063,930,589,184,505,269,008,083

    0  1  2  3  4  5  6  7  8  9
count[]:1  0  0  2  1  1  0  0  2  3
Addr[] :0  1  1  1  3  4  5  5  5  7

第一次排序(个位):以278为例addr[8] 为5,就把元素278放到数组5号位置,然后把addr[8]++

(1)LSD:从最低位开始排序,循环上面的操作,把次高位排序,再把最高位排序。

代码:

int GetMaxBit(int *arr,size_t size) //获取最大值的位数
{
	int count = 0;
	int radix = 1;
	for (size_t i = 0; i < size; ++i)
	{
		while (arr[i] > radix)
		{
			count++;
			radix *= 10;
		}
	}
	return count;
}
void RadixSortLSD(int *arr, size_t size) //按最低位开始排序
{
	size_t MaxBit = GetMaxBit(arr, size);
	int radix = 1;
	int* bucket = new int[size];
	for (size_t BitIdx = 1; BitIdx <= MaxBit; ++BitIdx)
	{

		//统计个位 出现的次数 放到桶中
		int count[10] = { 0 };
		for (size_t idx = 0; idx < size; ++idx)
		{
			count[arr[idx]/radix % 10]++;
		}

		//计算每个桶的起始位置: 上一个桶的起始地址+上一个桶内的元素个数
		int Addr[10] = { 0 };
		for (size_t j = 1; j < 10; ++j)
		{
			Addr[j] = Addr[j - 1] + count[j - 1];
		}
		//归置元素,排序

		for (size_t index = 0; index < size; ++index)
		{
			int k = arr[index] / radix % 10;//桶号
			bucket[Addr[k]] = arr[index];
			Addr[k]++;
		}
		memcpy(arr, bucket, size*sizeof(bucket[0]));
		radix *= 10;		
	}
	delete[] bucket;
}
(2) MSD以最高位排序是一个递归过程

   ①先把最高位排序,找出count[]数组中大于1的。

   ②再对个数大于1的,再次进行此低位排序。直到最低位。

代码中有解释:

void _RadixSortMSD(int *arr, size_t left, size_t right, int* bucket, int bit) //[)
{
	if (bit == 0)
		return;
	int radix = (int)pow(10,bit -1);

	//统计百(十 个)位 出现的次数 放到桶中
	int count[10] = { 0 };
	for (size_t idx = left; idx < right; ++idx)
	{
		count[arr[idx] / radix % 10]++;
	}

	//计算每个桶的起始位置: 上一个桶的起始地址+上一个桶内的元素个数
	int Addr[10] = { 0 };
	for (size_t j = 1; j < 10; ++j)
	{
		Addr[j] = Addr[j - 1] + count[j - 1];
	}
	//归置元素,排序

	for (size_t index = left; index < right; ++index)
	{
		int k = arr[index] / radix % 10;//桶号
		bucket[left + Addr[k]] = arr[index];
		Addr[k]++;
	}
	memcpy(arr + left, bucket + left, (right - left)*sizeof(bucket[0]));

	//扫描count桶中 查找个数大于1的元素
	size_t m = 0;
	for (; m < 10; ++m)
	{
		if (count[m] <= 1)
			continue;
		else
		{
			int begin = left + Addr[m] - count[m];
			int end = begin + count[m];
			_RadixSortMSD(arr, begin, end, bucket, bit - 1);
		}
	}
	
}


void RadixSortMSD(int *arr,size_t size)
{
	size_t bit = GetMaxBit(arr, size);
	int * bucket = new int[size];
	_RadixSortMSD(arr, 0, size, bucket, bit);
	delete[] bucket;
}



你可能感兴趣的:(数据结构,基数排序,MSD,LSD)