排序算法(四) 基数排序

来源:互联网 发布:人工智能疾病诊断 编辑:程序博客网 时间:2024/05/18 02:13

本篇博客介绍基于顺序表的实现 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;}



2 0