排序原理:
基数排序是一种非比较型排序算法,其原理是将整数按位数切割成不同的数字,然后按每个位数分别比较。由于整数也可以表达字符串(比如名字或日期)和特定格式的浮点数,所以基数排序也不是只能使用于整数。
排序思想:
数位来进行排序的.他是从个位开始,然后按照每一位的数进行排序
排序过程:
1.先按照个位进行排序
2.接着按照十位排序
3.重复这个过程,直到所有的位数已经被排过序了,并且如果这个过程中碰到在某个位上没有数的话就进行补零操作
实现步骤:
1.我们第一次遍历序列.找出序列中的最大值MAX,找到MAX之后我们可以确定我们需要比较多少数位了.
2.这时候我们就需要按照元素在该位数对应的数字将元素存入到相应的容器之中.如下图所示:
3.之后我们再按照容器的顺序将元素重新弹出构成我们接下来需要排序的序列,如下图所示:
这个从容器弹出的过程需要注意一点,那就是遵循先进先出的原则,所以这个容器选择队列或者是链表比较合适,不能选择栈,因为栈是先进后出,拿取元素的时候回非常麻烦.
4.最后只需要重复2,3步骤,直到最高位也比较完毕,那么整个基数排序就已经完成了.
动图演示
代码展示
//将所有的数组合并成原来的数组
public static void merge(ArrayList<Integer> list[],int num[]) {
int k=0;
for(int i=0;i<list.length;i++) {
if(list[i]!=null) {
for(int j=0;j<list[i].size();j++) {
num[k++]=list[i].get(j);
System.out.print(num[k-1]+" ");
}
}
//合并完成之后需要将链表清空,否则元素会越来越多
list[i].clear();
}
System.out.println();
}
//将所有的元素分散到各个链表之中
public static void split(ArrayList<Integer> list[],int num[],int k) {
for(int j=0;j<num.length;j++) {
list[num[j]/k%10].add(num[j]);
}
System.out.println("-----------------------------------------------------------------------");
System.out.println("个位开始数,第"+(String.valueOf(k).length())+"位排序结果:");
for(int j=0;j<10;j++) {
System.out.println((String.valueOf(k).length())+"号位,数值为"+j+"的链表结果:"+list[j]);
}
}
public static void main(String[] args) {
ArrayList<Integer>list[]=new ArrayList [10];
for(int i=0;i<10;i++) {
list[i]=new ArrayList<Integer>();
}
int []num ={7,14,9,333,201,1,88,6,57,10,56,74,36,234,456};
long startTime=System.currentTimeMillis();
int max=Integer.MIN_VALUE;
//第一次遍历获得序列中的最大值
for(int i=0;i<num.length;i++) {
if(num[i]>max)
max=num[i];
}
int k=1;
for(int i=0;i<String.valueOf(max).length();i++) {
split(list, num, k);
System.out.println("第"+(i+1)+"次排序");
merge(list, num);
k=k*10;
}
}
性能分析
稳定性:
稳定
时间复杂度
基数排序只需要根据最大元素的位数,遍历相应次数的序列即可,所以我们可以确定基数排序的时间复杂度一定是线性级别的,但是虽然是线性级别的,但是有一个系数的,这个系数就是最大元素的位数K,所以时间复杂度应该是O(n*k)
空间复杂度
空间复杂度主要就是取决于链表的数量以及序列元素的数量,所以空间复杂度为O(n+k)