基数排序

基数排序的描述

       基数排序是另外一种高效的线性排序算法。其方法是将数据按位分开,并从数据的最低有效位到最高有效位,依次排序,从而得到有序数据集合。例如:用基数排序对十进制数据{15,12,49,16, 36, 40}进行排序。在对各位数进行排序之后,其结果为{40,12,15, 16,36,49},在对十位进行排序之后,其结果为{12,15,16,36,40,49}。有一点非常重要,在对每一位数值进行排序时其排序过程必须是稳定的。因为,一旦一个数值通过较低有效位的值进行排序之后,此数据的位置不应该改变,除非经过较高有效位的值进行比较后需要它调整位置。

       基数排序实质上是在元素每一位上应用计数排序来对数据集合排序。从最低位开始,一个位置一个位置地应用计数排序来不断的调整元素。一旦调整完了最高有效位的数值,排序过程完成。获取每位数值的简单方法是使用幂运算和模运算。

 

 

基数排序的实现

// RadixSort.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <malloc.h>
#include "typedef.h"


/*
*函数名:RadixSort
*参数:pData  待排序数组数据的首地址
*      uiSize 数据的元素个数
*      p  待排序元素的位数
*      k  基数
*功能:对数组进行基数排序
*返回值:无
*作者:AlbertoNo1
*日期:2016-03-29
*/
VOID RadixSort(VOID *pData, UINT32 uiSize, UINT32 p, UINT32 k)
{
	INT32 i = 0;
	INT32 j = 0;
	INT32 n = 0;

	UINT32 uiIndex = 0; //元素在有序数组中的偏移值
	UINT32 uiPval = 0;

	UINT32 *puiData = NULL;
	UINT32 *puiTemp = NULL;
	UINT32 *puiCount = NULL;

	if (uiSize <= 1)
	{/*不用排序*/
		return ;
	}

	/*申请用于存放排序元素的内存*/
	puiTemp = (UINT32*)malloc(uiSize*sizeof(UINT32));
	if (NULL == puiTemp)
	{
		return ;
	}

	/*申请用于存放元素计数数组的内存*/
	puiCount = (UINT32*)malloc(k*sizeof(UINT32));
	if (NULL == puiCount)
	{
		free(puiTemp);
		return ;
	}

	puiData = (UINT32*)pData;

        for (n = 0; n < p; n++)
	{
		/*初始化计数频率数组*/
		for (j = 0; j < k; j++)
		{
			puiCount[j] = 0;
		}

		uiPval = (UINT32)pow((double)k, (double)n);

		/*按位统计每个元素出现的频率*/
		for (i = 0; i < uiSize; i++)
		{
			uiIndex = (puiData[i]/uiPval)%k;
			puiCount[uiIndex] += 1;
		}

		/*调整计数值*/
		for (j = 1; j < k; j++)
		{
			puiCount[j] = puiCount[j] + puiCount[j-1];
		}

		/*排序, 从后往前进行排序,保证了排序的稳定性*/
		for (i = uiSize-1; i >= 0; i--)
		{
			uiIndex = (puiData[i]/uiPval)%k;
			memcpy(&puiTemp[puiCount[uiIndex]-1], &puiData[i], sizeof(UINT32));

			puiCount[uiIndex] -= 1;
		}

		memcpy(puiData, puiTemp, uiSize*sizeof(UINT32));

	}

	free(puiTemp);
	free(puiCount);

	return ;
}


int _tmain(int argc, _TCHAR* argv[])
{
	INT32 iRet = 0;
	UINT32 uiLoop = 0;

	//UINT32 auiData[] = {10,15,15,18,20,20,20,36,48,51,51,77,77};
	UINT32 auiData[] = {77,77,51,51,48,36,20,20,20,18,15,15,10};
	//UINT32 auiData[] = {77,15,20,18,51,51,36,10,77,15,20,20,48};
	//UINT32 auiData[] = {77,77};
	//UINT32 auiData[] = {77};

	RadixSort(auiData, sizeof(auiData)/sizeof(auiData[0]), 2, 10);

	printf("Radix Sort Success.\n");
	printf("Result:\n");

	for (uiLoop = 0; uiLoop < sizeof(auiData)/sizeof(auiData[0]); uiLoop++)
	{
		printf("%d  ", auiData[uiLoop]);
	}

	getchar();
	return 0;
}


 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值