十大排序(四)

上几篇文章我们说的是比较类的排序,今天给大家分享一下非比较累的排序;非比较类中包含桶排序
:基数排序、桶排序、计数排序
十大排序(四)_第1张图片
计数排序
找出待排序的数组中最大和最小的元素;
统计数组中每个值为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;
    }

第一篇
第二篇
第三篇

你可能感兴趣的:(JAVA,排序算法,算法,数据结构)