上几篇文章我们说的是比较类的排序,今天给大家分享一下非比较累的排序;非比较类中包含桶排序
:基数排序、桶排序、计数排序
计数排序
找出待排序的数组中最大和最小的元素;
统计数组中每个值为i的元素出现的次数,存入数组C的第i项;
对所有的计数累加(从C中的第一个元素开始,每一项和前一项相加);
反向填充目标数组:将每个元素i放在新数组的第C(i)项,每放一个元素就将C(i)减去1。
/**
* @param A
* @param n
* @return
*/
public int[] countingSort(int[] A, int n) {
if(A==null ||n<2){
return A;
}
//找出桶的范围,即通过要排序的数组的最大最小值来确定桶范围
int min=A[0];
int max=A[0];
for(int i=0;i<n;i++){
min=Math.min(A[i],min);
max=Math.max(A[i],max);
}
//确定桶数组,桶的下标即为需排序数组的值,桶的值为序排序数同一组值出现的次数
int[] arr = new int[max-min+1];
//往桶里分配元素
for(int i=0;i<n;i++){
arr[A[i]-min]++;
}
//从桶中取出元素
int index=0;
for(int i=0;i<arr.length;i++){
while(arr[i]-->0){
A[index++]=i+min;
}
}
return A;
}
桶排序
取得数组中的最大数,并取得位数;
arr为原始数组,从最低位开始取每个位组成radix数组;
对radix进行计数排序(利用计数排序适用于小范围数的特点);
/**
* @param A
* @param n
* @return
*/
public int[] radixSort(int[] A, int n) {
//基于桶排序的基数排序
//确定排序的趟数,即排序数组中最大值为809时,趟数为3
int max=A[0];
for(int i=0;i<n;i++){
if(A[i]>max){
max= A[i];
}
}
//算出max的位数
int time=0;
while(max>0){
max/=10;
time++;
}
//【桶】初始化十个链表作为桶,用户分配时暂存
ArrayList<ArrayList<Integer>> list = new ArrayList<ArrayList<Integer>>();
for(int i=0;i<10;i++){
ArrayList<Integer> Item = new ArrayList<Integer>();
list.add(Item);
}
//进行time次分配和收集
for(int i=0;i<time;i++){
//分配元素,按照次序优先,从个位数开始
for(int j=0;j<n;j++){
int index = A[j]%(int)Math.pow(10,i+1)/(int)Math.pow(10,i);
list.get(index).add(A[j]);
}
//收集元素,一个一个桶地收集
int count=0;
//10个桶
for(int k=0;k<10;k++){
//每个桶收集
if(list.get(k).size()>0){
for(int a: list.get(k)){
A[count]=a;
count++;
}
//清除数据,以便下次收集
list.get(k).clear();
}
}
}
return A;
}
基数排序数据处理
计算原数据集中最大的元素,然后计算有几位
将原数据集遍历,通过个位进行比较,将比较出来的值放入对应编号为0-9的桶中
根据桶的编号将数据拿出排序一个返回集
拿到第三步的返回集,进行遍历,这个适合比较十位的位置,根据十位上的数字比较出来的值存入0-9对应的桶中。
重复第四步,直到最大元素的位数比较完成。
public int[] radixsort(int[] arr) {
int max=arr[0];
for(int i=1;i<arr.length;i++) {
if(arr[i]>max) {
max=arr[i];
}
}
int maxLength=(max+"").length();//得到数组最大值的位数,max+""将整型max转为字符串再利用字符串求长度方法length求max的位数
int[][] bucket=new int[10][arr.length];//此处10表示10个桶分别为0~9
int[] bucketElemCount=new int [10];//为了记录每个桶中,实际存放了多少个数据,我们定义一个一维数组来记录各个桶的每次放入的数据个数,比如:bucketElemCount[0],记录的就是bucket[0] 桶的放入数据个数
for(int i=0,n=1;i<maxLength;i++,n*=10){// n=1 表示处理个位,n=10表示处理十位,n=100表示处理百位 ......
for(int j=0;j<arr.length;j++) {
int digit=arr[j]/n%10;//取出每个元素的对应位的值
bucket[digit][bucketElemCount[digit]]=arr[j];//放入到对应的桶中
bucketElemCount[digit]++;
}
int index=0;
for(int k=0;k<bucketElemCount.length;k++) {//遍历每一桶,并将桶中的数据,放入到原数组
for(int l=0;l<bucketElemCount[k];l++) {
arr[index++]=bucket[k][l];
}
bucketElemCount[k]=0;//第i+1轮处理后,需要将每个 bucketElementCounts[k] = 0 即桶中数据置空方便下次使用
}
}
return arr;
}
第一篇
第二篇
第三篇