排序算法总结(五)——非比较排序

1.基数排序
这里的基数指的是位数:例如对十进制来说,指的是个位、十位、百位。

基本思想:
(1)首先设置号码为0-9的十个篮子;
(2)第一轮将序列的数字按照个位依次放置到对应号码的篮子中,并形成新的排序;
(3)第二轮在第一轮排序的基础上,按照十位依次放置到对应号码的篮子中,同样形成新的排序;
(4)依次类推,直到没有更好的位数,此时的排序即为最终的排序。
注意在放入篮子中的,不能改变元素本身相互之间的顺序,先遍历到的数字要先放进去。

具体示意图如下所示:
(图片来自https://www.cnblogs.com/ECJTUACM-873284962/p/6935506.html,侵权删)

第一轮排序后:
这里写图片描述
第二轮排序后:
这里写图片描述

代码实现:

public class JishuSort {

    public static void main(String[] args) {
        int[] a = {12,33,41,14,6,14};
        sort(a);

        for(int i = 0;i<a.length;i++)
            System.out.println(a[i]);
    }

    public static void sort(int[] a){
        int len = a.length;
        int max = a[0];
        //选出最大值,根据最大值得到最高位,计算循环次数
        for(int i=1;i<len;i++){
            if(a[i]>max){
                max = a[i];
            }
        }
        //定义二维数组记录排序存放排序数据,即十个篮子
        int[][] buckets = new int[10][len];
        //记录buckets中每个组里存放的数据个数,即每个篮子中放入的数据个数
        int[] num = new int[10];
        //使用1、10、100、1000等来记录位数
        int h = 1;

        while(h<max){

            //依次将数据放置到对应编号的篮子中
            for(int i = 0;i<len;i++){
                buckets[(a[i]/h)%10][num[(a[i]/h)%10]] = a[i];
                num[(a[i]/h)%10]++;
            }

            //将每轮排序后的结果返回到a
            int n = 0;
            for(int i = 0;i<10;i++){
                if(num[i]!=0){
                    for(int j = 0;j<num[i];j++){
                        a[n] = buckets[i][j];
                        n++;
                    }
                }
            //注意每轮排序后需要将num置为0,即将篮子清空
            num[i] = 0;
            }
            //增加位数
            h*=10;
        }
    }
}

2.桶排序
基本思想:根据数据的范围将其分配到不同的桶中,桶中的元素各自排序,最后合并到一起。

算法步骤:
(1)初始化建立一定数量的buckets;
(2)遍历原始序列,根据元素大小放置到对应的bucket中;
(3)对非空的buckets中的元素进行排序;
(4)按照顺序返回buckets中的元素到原始数组中即可完成排序。

可参看如下例子:
(图片来自https://img-blog.csdn.net/20150929092136858,侵权删)
这里写图片描述

代码实现:
参考:https://www.cnblogs.com/zer0Black/p/6169858.html

import java.util.ArrayList;
import java.util.Collections;

public class BucketSort {

    public static void main(String[] args) {
        int[] a = {12,33,41,14,6,14};
        sort(a);

        for(int i = 0;i<a.length;i++)
            System.out.println(a[i]);
    }

    public static void sort(int[] a){
        int max = a[0];
        int min = a[0];
        int len = a.length;

        //根据序列中的最大值和最小值确定bucket的数量
        for(int i = 1;i<len;i++){
            if(a[i] > max)
                max = a[i];
            if(a[i] < min)
                min = a[i];
        }

        //bucket的数量blen
        int blen = (max-min)/len + 1;

        //初始化bucket
        ArrayList<ArrayList<Integer>> buckets = new ArrayList<ArrayList<Integer>>(blen);
        for(int i = 0;i<blen;i++){
            buckets.add(new ArrayList<Integer>());
        }
        //在每个bucket中存放元素
        for(int i = 0;i<len;i++){
            buckets.get((a[i]-min)/len).add(a[i]);
        }

        //对bucket内元素进行排序
        for(int i=0;i<blen;i++){
            Collections.sort(buckets.get(i));
        }

         System.out.println(buckets.toString());
    }
}

3.计数排序
基本思想:对每一个元素x,确定小于x的元素个数。因此我们就可以直接把x放到最终输出数组中的相应位置上。

算法步骤:
(1)设置辅助数组count,长度为max-min+1;
(2)遍历无序序列,将元素依次放置到count数组对应序号的位置上,得到每个元素出现的次数,例如a[i]出现了3次,则count [a[i] - min] = 3;
(3)遍历count数组,使得count[i] = count[i]+count[i-1],由此得到小于i的元素的个数,即i在整个无序序列中应该拍在第count[i]位;
(4)建立临时数组temp,遍历无序序列,如a[i],根据count得到小于a[i]的个数,将a[i]直接放置到temp对应位置上。

代码实现:

public class CountSort {
    public static void main(String[] args) {
        int[] a = {12,33,41,14,6,14};
        int[] re = sort(a);

        for(int i = 0;i<re.length;i++)
            System.out.println(re[i]);
    }

    public static int[] sort(int[] a){
        int max = a[0];
        int min = a[0];
        int len = a.length;

        //计算序列最大值和最下值,确定count数组的长度为max-min+1
        for(int i = 1;i<len;i++){
            if(a[i]>max)
                max = a[i];
            if(a[i]<min)
                min = a[i];
        }

        int[] count = new int[max-min+1];
        int[] temp = new int[len];//临时数组

        //计算每个元素出现的次数
        for(int i=0;i<len;i++){
            count[a[i]-min]++;
        }

        //计算小于某元素的元素的个数
        for(int i=1;i<max-min+1;i++){
            count[i] = count[i] + count[i-1];
        }
        //将元素放置到temp对应位置中,并且记得每放置一个元素,对应的count--;
        for(int i = 0;i<len;i++){
             if(count[a[i]-min]!=0){
                 temp[count[a[i]-min]-1] = a[i];
                 count[a[i]-min]--;
             }  
        }
        return temp;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值