[古典的なソートアルゴリズム] 8。カウントソート

以前の並べ替えは、比較並べ替えに基づいています。後者のバケットソートと基数ソートを含む、カウントソートはそうではありません。

名前が示すように、ソートのカウントは、ソートする要素の出現回数を記録します。新しい配列を指定します。配列インデックスは格納された要素を記録するために使用され、配列番号は要素の出現回数を記録します。

カウントソートは、特定の改善の後、場違いで安定した線形時間ソートアルゴリズムになります。このソートは、シーケンス分布が比較的集中していて、境界が既知で比較的小さく、ソートの要素が整数でなければならない状況に適しています。シーケンス分布がまばらで境界が大きすぎると、新しい配列を開くことによって占有されるスペースが大きくなります。

public class Main {

    public static void main(String[] args) {
        int[] arr = {3, 3, 5, 6, 2, 1};
        System.out.print("排序前:");
        arrPrint(arr);
        int[] out = CountSort(arr);
        System.out.print("排序后:");
        arrPrint(out);
    }

    // 计数排序
    //
    // 初始化max和min为arr的第一个元素,第一个for循环反复取arr中的最大值赋给max,
    // 反复取arr中的最小值赋给min,这样就得到arr中的最大最小值max,min。
    // max-min+1的长度就是计数数组count的长度。
    // 第二个for循环,将arr中元素的出现次数在count中计数,count的索引为 元素-min,
    // count的元素表示对应arr元素的出现次数,(本实例得到的count为[1, 1, 2, 0, 1, 1])。
    // 简单版本的计数排序索引直接用来存储arr元素,因为索引必须从0开始,
    // 假如arr中的min是100,max是110,arr元素分布在100-110,
    // 那开辟的count数组中0-99的位置都被浪费了。所以我们的count数组长度设为
    // arr最大max到最小值min的长度max-min+1,arr元素对应的索引值即为 元素-min。
    // 第三个for循环,遍历计数数组count中的元素,将前面的计数结果累加到后一位的计数结果中
    // (本实例得到的count为[1, 2, 4, 4, 5, 6])。count的索引与arr元素对应关系不变,
    // 此时count的元素表示小于等于对应arr元素的元素数量。比如实例arr中的2这个数字,
    // 对应到count的索引为 2-min = 2-1 = 1,索引元素count[1]=2,所以小于等于arr中2这个数
    // 的数字总共有 count[1]=2 个。
    //
    // 创建输出结果数组result,
    // 第四个for循环,倒叙遍历待排序数组arr,遍历索引为j,遍历元素为arr[j],
    // 那么对应到count的索引为arr[j]-min,索引对应元素为count[arr[j]-min],
    // 那么根据count数组的含义,在arr中,小于等于arr[j]的元素总共有count[arr[j]-min]个,
    // 不算上arr[j]等于arr[j]自己这种情况,那么小于等于arr[j]的元素除自己以外,
    // 总共有count[arr[j]-min] - 1个。既然有 count[arr[j]-min] - 1 个数字小于等于arr[j],
    // 那么数组排序的时候,arr[j]在数组里就应该排名第 count[arr[j]-min] - 1 位这个位置。
    // 我们直接在result的count[arr[j]-min] - 1这个位置将arr[j]填入。
    // 即result[count[arr[j] - min] - 1] = arr[j]。填入result之后,
    // arr[j]在计数数组count的对应计数 count[arr[j]-min] 减1,j继续向左遍历,
    // 如此循环反复,最后可将arr中的数按照它们对应的大小排序好。循环结束,返回result即可。
    private static int[] CountSort(int[] arr) {
        int max = arr[0];
        int min = arr[0];
        for (int i = 1; i < arr.length; i++) {
            if (max < arr[i])
                max = arr[i];
            if (min > arr[i])
                min = arr[i];
        }

        int[] count = new int[max - min + 1];
        for (int num: arr) {
            count[num - min]++;
        }
        for (int i = 1; i < count.length; i++) {
            count[i] += count[i - 1];
        }

        int[] result = new int[arr.length];
        for (int j = arr.length - 1; j >= 0; j--) {
            result[count[arr[j] - min] - 1] = arr[j];
            count[arr[j] - min]--;
        }
        return result;
    }

    // 辅助函数:将int[] 打印出来
    private static void arrPrint(int[] arr) {
        StringBuilder str = new StringBuilder();
        str.append("[");
        for (int v : arr) {
            str.append(v + ", ");
        }
        str.delete(str.length() - 2, str.length());
        str.append("]");
        System.out.println(str.toString());
    }
}


例のアニメーションデモンストレーションは次のとおりです。

ここに画像の説明を挿入します

おすすめ

転載: blog.csdn.net/fisherish/article/details/114280356