排序算法——基数排序

(radixsort)则是属于“分配式排序”(distributionsort),基数排序法又称“桶子法”(bucketsort)或binsort,顾名思义,它是透过键值的部份资讯,将要排序的元素分配至某些“桶”中,藉以达到排序的作用,基数排序法是属于稳定性的排序,其时间复杂度为O(nlog(r)m),其中r为所采取的基数,而m为堆数,在某些时候,基数排序法的效率高于其它的比较性排序法。

基本实现:

以LSD(从低位到高位)为例

一组数据:123,231,243,456,436,578,567,546,598,674,656,789,876,896,987,999

首先根据个位数的数值,在走访数值时将它们分配至编号0到9的桶子中:

0:                                           

1:231

2:

3:123 243 

4:674 

5:

6:456 436 546 656 876 896

7:567 987

8:578 598 

9:789 999

接下来将这些桶子中的数值重新串接起来,成为以下的数列:

231 123 243 674 456 436 546 656 876 896 567 987 578 598 789 999

重复以上步骤,最大数有多少位就重复多少次

具体代码实现:

#define _CRT_SECURE_NO_WARNINGS


#pragma once
#include <string.h>


int GetMaxBit(int* array, int size)    //求最大数有多少位
{
size_t count = 1;
int radix = 10;
for(size_t idx = 1;idx<size; ++idx)
{
while(array[idx]>=radix)
{
count++;
radix *= 10;
}
}
return count;
}




void RadixSortLSD(int arr[], size_t size)
{
//1.确定最大值有多少位
int bit = GetMaxBit(arr,size);
int radix = 1;
    int *bucket = new int[size];    //辅助空间桶
for(size_t idx = 0;idx < bit; ++idx)
{
int count[10] = {0};
for(size_t idx = 0; idx< size; ++idx)
{
count[arr[idx]/radix%10]++;//2.统计每个radix位上出现的数字次数
}
//3.寻找每个桶的起始位置
int Addr[10] = {0};
for(size_t idx = 1;idx<10; ++idx)
{
Addr[idx] = Addr[idx-1]+count[idx-1];
}
//4.将元素放置到对应的桶中
for(size_t idx = 0; idx < size; ++idx)
{
int k = arr[idx]/radix%10;//寻找桶的位置
bucket[Addr[k]] = arr[idx];//Addr[k]是这个桶的起始位置
Addr[k]++;
}
//5.将元素放回原空间
memcpy(arr,bucket,size*sizeof(arr[0]));
radix *=10; //排序前面一位
}

delete[] bucket;
}

从最好位开始分配(MSD):

从最高位开始分配,每次分配完之后又要对每个桶中的元素分配,变为了子问题,所以采用递归

#pragma once


#include <string.h>
#include <math.h>
int GetBit(int *arr, size_t size)
{
size_t count = 1;
int radix = 10;
for(int idx = 0; idx< size; ++idx)
{
while(arr[idx]> radix)
{
count++;
radix*= 10;
}
}
return count;
}

void _RadixSort(int arr[], size_t left,size_t right, int bit,int * bucket)  //因为每个桶的起始位置不同,元素数目不同,所以传入左边界和右边界,左闭右                                                                                                         //开
{
if(bit < 1)
return ;
 int radix = (int)pow(10.0, bit -1);

int count[10] = {0};
for(size_t idx = left; idx< right; ++idx)
{
count[arr[idx]/radix%10]++;//求radix位出现的次数是为了确定每个桶的位置
}
//确定每个桶的起始位置
int Addr[10] = {0};
for(size_t idx = 1; idx < 10; ++idx)
{
Addr[idx] = Addr[idx-1] + count[idx-1];
}
//将其放入辅助空间中
for(size_t idx = left; idx < right; ++idx)
{
int k = arr[idx]/radix%10;  //确定arr[idx]是属于哪个桶的
bucket[Addr[k]+left] = arr[idx];//一定要注意每个桶的起始位置;此时是以左边界left开始的,不是从0开始的
Addr[k]++;
}
memcpy(arr+left,bucket+left,(right-left)*sizeof(arr[0]));   //拷贝时室对每个子桶进行拷贝,不都是对全部元素拷贝,
for(size_t idx = 0; idx < 10; ++idx)
{
if(count[idx]<=1)
continue;
else
{
int begin = left+Addr[idx]-count[idx]; //应该注意前面往桶中放元素的时候Addr[idx]已经加到了该桶的最后位置,也就是其右开区间

//所以下个子桶的起始位置时应该加上left并且减去其中的元素
int end = begin+count[idx];
_RadixSort(arr, begin, end, bit - 1, bucket);
}


}

}


void RadixSort(int arr[], size_t size)
{
int bit = GetBit(arr, size);
int *bucket= new int[size];
_RadixSort(arr,0,size,bit,bucket);
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值