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

 基数排序

 基本思想

基数排序(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的桶(个位数值与桶号一一对应)中。分配结果(逻辑想象)如下图所示:

基数排序算法(排序详解)_第1张图片

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

81  22 73  93  43 14  55  65 28  39

 

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

 基数排序算法(排序详解)_第2张图片

 算法实现(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 num[] = new Vector[10];
					for (int i = 0; i < num.length; i++) {
						num[i] = new Vector();
					}

					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 plus = new Vector(); // 储存正数
				Vector minus = new Vector(); // 储存负数
				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);
				}
			}


 效率分析

算法性能:

基数排序算法(排序详解)_第3张图片

时间复杂度:

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

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

空间复杂度

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

算法稳定性

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

你可能感兴趣的:(基数排序算法(排序详解))