基数排序

定义

与其他常规排序方式不同,基数排序不是根据元素的大小进行调换位置,进而形成有序列表,或者更严格来讲,基数排序不是直接根据元素整体的大小进行元素比较,而是将原始列表元素分成多个部分,对每一部分按一定的规则进行排序,进而形成最终的有序列表。

示例:扑克牌排序

排序方式:可以先按照牌的种类排序,例如红桃都在梅花前面,如排序规则为:"红桃"<"方块"<"梅花"<"黑桃",则排序后的结果为四个不同类型的牌堆,再按照牌的数值大小排序,则可以保证在排序之后:相同数值的牌,"红桃"在前,"黑桃"在后,不同数值大小的牌,则按照大小排序。

以两种颜色进行简单演示


由此可得知:基数排序的目的就是在按照上一套排序规则之后,形成的"已排序"列表中,按照新的规则,在"已排序"基础上再次进行排序。

与其他的排序方式比较可知:快排、堆排、希尔排序等,这些排序更偏重于利用数据结构特性减少时间复杂度和空间复杂度,基数排序则更偏重于提供多种排序规则,对复杂对象可以满足在不同的部分,按照不同的规则进行排序(或者说可以标志对象的某一部分在列表中的优先级)

示例

以基数排序常用形式作为示例,即对一个整数数组进行排序,此处排序方式为:先按照元素个位上数字进行排序,再按照十位数字、百位数字。。。,最终形成的即为有序数组(负数需要分成另一部分操作,此处不考虑)。

演示数组:53,28,31,9,33,191,图示如下:


参考代码

public class t{
	public static void main(String[] args){
		int[] arr=new int[]{11,9,23,98,143,78,20,26,23,7,19,0,65,33};
		Base.sort(arr);
		for(int i:arr){
			System.out.print(i+" ");
		}
		System.out.println();
	}
}
class Base{
	public static void sort(int[] arr){
		boolean flag=true;//判断结束标志,待检查位数超过最高位结束
		int index=0;//设定待检查位数
		node[] base=new node[10];
		while(flag){
			flag=false;
			flag=check(base,arr,index);
			index++;
		}
	}
	/*
		完成数组arr与,数组链表base,两者之间的转换
		addElement: arr->base
		getElement: base->arr
	*/
	private static boolean check(node[] base,int[] arr,int index){
		boolean flag=false;
		int pos=0;//待存储的位置,也就是index位上的数字
		int count=0;//表示arr数组待存储元素的位置
		for(int i=0;i<arr.length;i++){
			pos=(int)(arr[i]/Math.pow(10,index))%10;//获得index位上的数字
			if(!flag&&pos!=0){//当数组中pos位全部为0,停止
				flag=true;
			}
			addElement(base,pos,arr[i]);//把整个值添加到数组链表结构中
		}
		//show(base);//观察中间过程
		for(int i=0;i<base.length;i++){
			count=getElement(base,i,arr,count);//把数组链表结构中数据转移会arr数组
		}
		return flag;
	}
	/*
		把value值,即数组上的值,存储到对应的数组链表结构的pos位置
	*/
	private static void addElement(node[] base,int pos,int value){
		node tem=base[pos];
		if(tem==null){
			tem=new node(value);
			base[pos]=tem;
		}else{
			while(tem.next!=null){
				tem=tem.next;
			}
			tem.next=new node(value);
		}
	}
	/*
		把数组链表结构pos位置的值,存储到数组中
	*/
	private static int getElement(node[] base,int pos,int[] arr,int count){
		node tem=base[pos];
		while(tem!=null){
			arr[count]=tem.value;
			tem=tem.next;
			count++;
		}
		base[pos]=null;//置空
		return count;
	}
	//观察中间转换过程
	private static void show(node[] base){
		node tem=null;
		for(int i=0;i<base.length;i++){
			tem=base[i];
			while(tem!=null){
				System.out.print(i+": "+tem.value+" ");
				tem=tem.next;
			}
			System.out.println();
		}
	}
}
class node{//便宜行事,属性公有访问
	public int value;
	public node next=null;
	public node(int value){
		this.value=value;
	}
}

总结

按照不同位上数字的方式进行基数排序,对于相同大小的元素,不需要改变相对位置,即稳定排序。对每一位上排序,将数组arr转换到数组链表结构base上为O(n),将数组链表结构base再转换到数组arr上为O(r),最大数据为d位,总复杂度为O(d*(n+r))。

结合上述函数解释,即对个数上数字或者百位上数字都一样,即使为0,也需要将arr上该元素存储到base结构中,即每一个元素都要调用addElement函数,所以为O(n);将base结构上不为空的链表上数据转移回数组arr上,即每一个不为空的链表都要调用getElement函数,所以为O(r)。整个数组的最大元素为d位,则复杂度为O(d*(n+r))。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值