请解释此计数排序中的代码

时间:2017-01-15 07:27:57

标签: c++ arrays sorting

我正在学习从教程中排序,我的C ++源代码如下:

#include <iostream>
#include <string.h>
using namespace std;

void countSort(int arr[], int size)
{
    //declare output array
    int output[size];
    //declare count array
    int count[size];
    //initialize count[] with zero
    //memset ( void * ptr, int value, size_t num )
    memset(count, 0, sizeof(count));

    //input array element is the index of count array
    //storing the repetition/frequency
    for(int i=0; i<size; i++){
        count[arr[i]]++;
    }


    /*
        Modify the count array such that each element at 
        each index stores the sum of previous counts.
    */
    // i=1 because, previous is 0 due to avoid -1
    for(int i=1; i<size; i++){
        count[i] += count[i-1];
    }

    //Build ouput array
    //count array element is the index of output array 
    for(int i=0; i<size; i++){
        //***********THIS LINE***********
        output[count[arr[i]]-1] = arr[i];
        count[arr[i]]--;
    }

    //copy ouput array into input array arr[]
    for(int i=0; i<size; i++){
            arr[i] = output[i];
    }

}

void printArray(int arr[], int size){
    // Ascending order
    for(int i=0; i<size; i++){
        cout<<arr[i]<<" ";
    }   
    cout<<endl;

}

int main() {
    // your code goes here
    int arr[] = {1,4,1,2,7,5,2,6,6,9};
    int size= sizeof(arr)/sizeof(arr[0]);
    countSort(arr, size);
    printArray(arr, size);
    return 0;
}

我理解在输出数组中取排序数组。但是为什么我们需要将输出索引递减-1:

output[count[arr[i]]-1] = arr[i];

我不明白这一部分。我只尝试output[count[arr[i]]],但它没有给我正确的排序数组。

1 个答案:

答案 0 :(得分:4)

计数数组被转换为结束索引数组,指向每个逻辑桶末尾的第1个,因此从每个索引中减去1。这可以组合使用预先减少,并且阵列向后扫描:

    for(i=size; i; ){
        i--;
        output[--count[arr[i]]] = arr[i];
    }

在总结之后回到计数,注意count [0]包含所有元素的计数等于零,count [1]包含所有元素的计数==零和所有元素== 1,依此类推,因此count [0]是包含零的桶的逻辑大小,并且大小比最后一个元素的索引大1。相同的逻辑适用于count [1],依此类推。

将计数转换为起始索引的示例代码。 output []转换为使用new(以避免堆栈溢出,而某些编译器不支持可变长度数组)。 count [10]假设数字范围限制为0到9。

#include <iostream>
#include <stdlib.h>
using namespace std;

void countSort(int arr[], int size)
{
    //declare output array
    int * output = new int[size];
    //declare count array
    // assumes range of values is 0 to 9
    int count[10];
    //initialize count[] with zero
    for(int i=0; i<size; i++)
        count[i] = 0;
    //input array element is the index of count array
    //storing the repetition/frequency
    for(int i=0; i<size; i++){
        count[arr[i]]++;
    }
    // convert counts into starting indices (this is the main change)
    int sum = 0, tmp;
    for(int i=0; i<size; i++){
        tmp = count[i];
        count[i] = sum;
        sum += tmp;
    }
    //Build ouput array
    //count array element is the index of output array 
    for(int i=0; i<size; i++){
        output[count[arr[i]]++] = arr[i];
    }
    //copy ouput array into input array arr[]
    for(int i=0; i<size; i++){
            arr[i] = output[i];
    }
    delete[] output;
}

void printArray(int arr[], int size){
    // Ascending order
    for(int i=0; i<size; i++){
        cout<<arr[i]<<" ";
    }   
    cout<<endl;
}

int main() {
    int arr[] = {1,4,1,2,7,5,2,6,6,9};
    int size= sizeof(arr)/sizeof(arr[0]);
    countSort(arr, size);
    printArray(arr, size);
    return 0;
}