基数排序

基数排序

算法思想:给定的一组数据,想按照个位数开始排序,放入对应序号桶中,然后统一取出后,再按十位数大小继续放入对应的桶中……依次类推,直到全部数据有序。
看一个例子:对数组56,78,12,248,103,89,34进行排序
步骤:
首先,按照每个数据的个位数进行排序得下图
在这里插入图片描述
重新整理后得到arr为:12,2,103,34,56,78,48,89
再按照十位数大小进行排序,得如下图
在这里插入图片描述
整理后得到arr:2,103,12,34,48,56,78,89
最后按照百位数进行排序得下图:
在这里插入图片描述
最终得到有序数列
2,12,34,48,56,78,89,103。
综上不难看出,排序得趟数为待排序数组中最大数得位数,上述例子中最大数为103,所以需要排3次序,才能得到最终有序数列。

定义桶号的意义
这里的桶号,其实可以理解成一个计数器,它是记录每一个桶号下的元素的个数,它为每趟排完序的数列中每一个元素应该放的位置提供了帮助。
这里举上面例子中第一趟排完序的例子:
在这里插入图片描述
首先,先将每一个桶号下标为1的数据开始,依次加上它前一个下标下的数据,即下图
在这里插入图片描述

这里需要从后向前开始确定每一个数据的位置,待排序的数组中最后一个元素是34,它在排完一趟后的的数组中的位置是3,这个3是通过34按个位数对应的桶号即4,桶号4中的数据-1得到的,即4-1=3,同理89的位置是7,是通过89按个位对应的桶号中的数据8-1=7得到的,依次类推,就可以确定每一个数据在排完序后的数组中的对应位置。每次确定一个数据后,bucket中对应桶号中的数据要自减1。这里桶号中的数据指的是上图中最下面红色一行的数据

算法实现

//确定待排序数组中最大数的位数
int GetMaxNumSeat(vector<int> arr)
{
  int max = arr[0];
  int num = 0;
  for(int i = 1;i<arr.size();i++)
  {
    if(max < arr[i])
      max = arr[i];
  }
  while(max)
  {
    num++;
    max/=10;
  }
  return num;
}
void RadixSort(vector<int> &arr)
{
  int num = GetMaxNumSeat(arr);//获取最大数的位数
  vector<int> tmp;//中间变量存访临时数据
  tmp.resize(arr.size(),0);//初始化
  int idx = 1;//开始获取最低位
  int number;//计算每次的桶号
  for(int i = 0;i<num;i++)
  {
    vector<int> bucket;//j计数器
    bucket.resize(10,0);//初始化
    for(int j = 0;j<arr.size();j++)
    {
      number = (arr[j] / idx) % 10;//获取个位,十位.....以此类推
      bucket[number]++;//记录每一个位置的元素个数
    }
    //依次累加方便后续记录位置
    for(int k = 1;k<10;k++)
    {
      bucket[k] = bucket[k - 1] + bucket[k];//将每一位的元素次数加起来,方便后续找寻每个元素的位置
    }
    //从后向前记录位置
    for(int j = arr.size() - 1;j >= 0;j--)
    {
      number = (arr[j] / idx) % 10;获取个位,十位.....依次找桶号
      tmp[bucket[number] - 1] = arr[j];//将每个数对应排完序的位置赋给临时数组tmp
      bucket[number]--;//计数器减1
    }
    swap(arr,tmp);//交换arr和tmp
    idx*=10;//idx扩大10倍寻找下一位数
    bucket.clear();//每次循环要把bucket清空一次
    tmp.clear();//中间临时数组清空
    tmp.resize(arr.size(),0);//重新初始化
  }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值