计数排序

计数排序

描述:
对每一个输入元素x, 确定小于x的元素个数。利用这一信息,就可以直接把x放到它在输入数组中的位置上。例如,有17个元素小于x, 则x就应该放在第18个输出位置上。当有几个元素相同时候,这一方案需要略作修改。

修改:
只要知道x 有几个元素,假如这里x有2个元素,那么将第1个x放在第18个元素,第2个x放在第19个元素。如果这时候有一个y 元素=x+1,那么y元素所放的位置 = 比x的元素个数+ x元素个数。这就是整个算法的原理。

算法:在计算机中需要用一个temp数组来存放对应元素的位置信息。

package com.zq.algorithm.sort;

/**
 * Created by zhengshouzi on 2015/11/7.
 */
public class CountSort {

    public static void main(String[] args) {
        int[] a = {2,6,9,10,87,45,21,44,29,37,100,200,187,243,567,88};
        int[] d ={2,5,3,0,2,3,0,3};

        countSort(a);
        //输出排序后的值
        for (int c :a){
            System.out.print(" "+ c);
        }
    }

    public static void countSort(int[] a){
        //一个备份数组,用来存放数组 a 的拷贝,
        int[]  b = new int[a.length];
        //找出待排序数组中的最大值,和最小值
        int max=a[0];
        int min=a[0];
        for (int i = 0; i < a.length; i++) {
            if (max<a[i]){
                max = a[i];
            }
            if (min>a[i]){
                min=a[i];
            }
            //赋值给备份数组
            b[i]=a[i];
        }
        //定义零时数组的大小
        int[] temp = new int[max-min+1];

        //对零时数组赋值
        for (int i = 0; i < a.length; i++) {
            //零时数组每一个元素的值,应该是 a 数组相应元素的个数值。如果a 中有 2个元素7,那么最终temp[7-min] = 2,,
            temp[a[i]-min]++;
        }
        //改变零时数组的值
        for (int i = 1; i < temp.length; i++) {
            //为什么需要改变呢?  因为  temp数组中的每一个值,都表示 a数组中有多少个对应的元素,   那么贱temp[2] + temp[1] 就表示,比 a[i]-min=2这个a[i] 小的元素有多少个了。
            temp[i] = temp[i]+temp[i-1];
        }
        //这里就是关键的地方,通过上面计算过后的temp的值,去改变 a 数组中的排序。
        //这里for循环由小到大,是不稳定排序,由大到小是稳定排序。
        for (int i = 0; i <a.length; i++) {
            int j = temp[(b[i]-min)];
            a[--j] = b[i];
            temp[a[i]-min]--;
        }
    }
}

时间复杂度:O(n+k), 空间复杂度O(n+k), k=最大元素-最小元素+1.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章