计算排序,为什么使用累积

时间:2016-05-31 08:44:55

标签: java sorting counting-sort

我在许多网站上查看了计算排序的代码。 他们使用累积的计数总和然后进一步的数组索引。 我打算问为什么他们不使用普通阵列打印:

好像[计数中origArray(i)的数量(origArray(i))!= 0],循环计数(origArray(i))并打印i。

这是因为使用Counting排序的要点是NO COMPARISON,并且在我的代码中与0进行比较。

请参阅此代码:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;

public class CountingSort {
    public static void main(String... args) throws IOException {
        new CountingSort().sort();
    }

    private void sort() throws IOException {
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        String line;
        int max = 0;
        String data = "";
        while ((line = reader.readLine()) != null && line.length() != 0) {
            data += line;
        }
        String[] ip = data.split(" ");
        int[] intArray = new int[ip.length];
        for (int i = 0; i < ip.length; i++) {
            intArray[i] = Integer.parseInt(ip[i]);
            if (intArray[i] > max)
                max = intArray[i];
        }
        int[] count = new int[max+1];
        Arrays.fill(count, 0);
        for (int i = 0; i < intArray.length; i++) {
            ++count[intArray[i]];
        }
        for (int i = 0; i < max; i++) {
            if (count[i] != 0) {
                for (int j = 0; j < count[i]; j++)
                    System.out.print(" " + i);
            }
        }
    }

}

3 个答案:

答案 0 :(得分:2)

您共享的链接上的实施不会打印System.out.print(" " + i),因为他们认为i与要排序的项目不同。如果你想对char进行排序,那将是真的,因为你需要一个演员。

由于您使用的是整数,因此您的实现没有任何问题。实际上,您最终得到了维基百科上提到的算法的一种变体:

  

如果要排序的每个项本身都是一个整数,并且也用作键,那么可以组合计数排序的第二个和第三个循环;在第二个循环中,不要计算应将键i放在输出中的位置,而只需将数字Count[i]的{​​{1}}个副本附加到输出中。

答案 1 :(得分:0)

累计总和是计算重复次数:您的数组中值可能是值的200倍。在这种情况下,count[200]将具有值3.因此,您需要将其打印三次(代码中的最后一个for循环)。

在排序算法中,&#34;比较&#34;意味着将数组的值相互比较。在该算法中没有这样的比较。

此算法在O(n)中的复杂性,但如果要排序的值可能很大,则需要大量存储。

答案 2 :(得分:0)

在您的实现中,您试图从 count 数组生成排序的输出。如果要从未排序的整数数组中生成已排序的列表,那会很好。

但是,现在,我将讨论无法从 count 数组生成输出的问题场景。

假设我们有一个包含两个字段( categoryID itemName )的数据列表。我们可以假设字段 categoryID 在[0..10]范围内。我们想通过计数排序算法来基于 categoryID 创建一个排序列表。下面给出了示例输入和输出:

Unsorted Items -->
2  Computer
5  Shirt
3  Bier
0  Soap
2  Laptop
3  Vodka
0  Lotion
3  Whiskey


Sorted Items -->
0  Soap
0  Lotion
2  Computer
2  Laptop
3  Bier
3  Vodka
3  Whiskey
5  Shirt

现在,我们可以轻松计算每个类别的项目数。但是,根据该计数信息,我们无法生成同时包含 categoryID productName 的输出。

因此,计数排序使用累积总和的想法,这实际上是一种计算项目在输出数组中的最终索引的方法。这是此问题的解决方案。

#include <iostream>
#include <vector>
#include <string>
using namespace std;

class Data
{
public:
    //let's assume category ID is in range [0..10]
    //Therefore, We can use counting sort for array of Data
    int category;
    string name;
    Data(){}
    Data(int id, string str)
    {
        category = id;
        name = str;
    }
};

vector<Data> Counting_Sort(vector<Data> A)
{
    int k = 10; //maximum category
    vector<int> C(k+1,0);
    for(int i=0; i<A.size(); i++)
    {
        C[ A[i].category ] = C[ A[i].category ] + 1;
    }

    for(int i=1; i<=k; i++)
    {
        C[i] = C[i-1] + C[i];
    }

    vector<Data> B(A.size() + 1);
    for(int i = A.size()-1; i>=0; i--)
    {
        B [ C [ A[i].category ] ] = A[i];
        C [ A[i].category ] = C [ A[i].category ] - 1;
    }

    vector<Data> ans(B.begin()+1, B.end());
    return ans;
}

void Show(vector<Data> vals)
{
    for(Data val:vals) cout<<val.category<<"  "<<val.name<<endl;
}

vector<Data> inputData()
{
    int numberOfItems = 8;
    string productNames[] = {"Computer", "Shirt", "Bier", "Soap", 
                             "Laptop", "Vodka", "Lotion", "Whiskey"};
    int categoryID[] = {2,5,3,0,2,3,0,3};
    vector<Data> inData;
    for(int i=0; i<numberOfItems; i++)
    {
        Data data(categoryID[i], productNames[i]);
        inData.push_back(data);
    }
    return inData;
}
int main()
{
    vector<Data> A = inputData();
    cout<<"Unsorted Items --> "<<endl;
    Show(A);
    vector<Data> ans = Counting_Sort(A);
    cout<<"\n\nSorted Items --> "<<endl;
    Show(ans);
    return 0;
}

希望有帮助!