基数排序算法(排序详解)

 基数排序

 基本思想

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

 操作方法

(1)假设有欲排数据序列如下所示:73 22 93 43 55 14 28 65 39 81首先根据个位数的数值,在遍历数据时将它们各自分配到编号0至9的桶(个位数值与桶号一一对应)中。分配结果(逻辑想象)如下图所示:


(2)分配结束后。接下来将所有桶中所盛数据按照桶号由小到大(桶中由顶至底)依次重新收集串起来,得到如下仍然无序的数据序列:

81  22 73  93  43 14  55  65 28  39

 

(3)接着,再进行一次分配,这次根据十位数值来分配(原理同上),分配结果(逻辑想象)如下图所示:

 

 算法实现(Java)

           

			// 基数排序的实现,有两种方式,低位优先法,适用于位数较小的数排序 简称LSD
			// 高位优先法,适用于位数较多的情况,简称MSD
			// 这里实现低位优先法
			public static void LSDSort(int a[]) {
				int max = a[0];
				for (int i = 1; i < a.length; i++) {
					if (a[i] > max)
						max = a[i];
				}
				int len = 0; // 存贮最大的数的位数,用来判断需要进行几轮基数排序
				while (max > 0) {
					max = max / 10;
					len++;
				}

				for (int times = 0; times < len; times++) // 按位数运行几次,每次都分裂成10份,在顺序链接
				{
					// 以下内容应为每次运行时,分割成0-9 个桶,然后顺序链接
					@SuppressWarnings("unchecked")
					Vector<Integer> num[] = new Vector[10];
					for (int i = 0; i < num.length; i++) {
						num[i] = new Vector<Integer>();
					}

					int k = 1; // 用来取出当前的对应的位数的数
					for (int i = 0; i < times; i++) {
						k = k * 10;
					}

					for (int i = 0; i < a.length; i++) // 对每一个数进行判断位数
					{
						int x = 0; // 用来表示当前的位数上的数的大小
						x = Math.abs(a[i]) / k; // 使用绝对值,防止受到正负号的影响
						x = x % 10;
						num[x].add(new Integer(a[i]));
					}
					// 将排序的结果顺序连接起来
					int count = 0;
					for (int i = 0; i < num.length; i++) {
						for (int j = 0; j < num[i].size(); j++) {
							a[count++] = num[i].get(j).intValue();
						}
					}
				}

				// 判断完绝对值大小顺序后,需要判断正负了
				Vector<Integer> plus = new Vector<Integer>(); // 储存正数
				Vector<Integer> minus = new Vector<Integer>(); // 储存负数
				for (int i = 0; i < a.length; i++) {
					if (a[i] <= 0) {
						minus.add(new Integer(a[i]));
					} else {
						plus.add(new Integer(a[i]));
					}
				}
				int count = 0;
				for (int i = minus.size() - 1; i > 0; i--) // 因为这是按照绝对值大小排列的,所以要倒序
				{
					a[count++] = minus.get(i);
				}
				for (int i = 0; i < plus.size(); i++) {
					a[count++] = plus.get(i);
				}
			}


 效率分析

算法性能:


时间复杂度:

在基数排序中,r为基数,d为位数。则基数排序的时间复杂度为O(d(n+r))。

我们可以看出,基数排序的效率和初始序列是否有序没有关联。

空间复杂度

对于任何位数上的基数进行“装桶”操作时,都需要n+r个临时空间。

算法稳定性

在基数排序过程中,每次都是将当前位数上相同数值的元素统一“装桶”,并不需要交换位置。所以基数排序是稳定的算法。

  • 18
    点赞
  • 93
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值