阵列计数排序分段故障

时间:2015-01-16 16:35:41

标签: c arrays counting-sort

您好我正在尝试使用计数排序来对从文件中读取的数字进行排序。这是我的代码:

    void CountingSort(int array[], int k, int n)
{
    int i, j;
    int B[100], C[1000];
    for (i = 0; i <= k; i++)
    {
        C[i] = 0;
    }

    for (j = 1; j <= n; j++)
    {
        C[array[j]] = C[array[j]] + 1;
    }

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

    for (j = 1; j <= n; j++)
    {
        B[C[array[j]]] = array[j];
        C[array[j]] = C[array[j]] - 1;
    }

    printf("The Sorted array is : ");
    for (i = 1; i <= n; i++)
    {
        printf("%d ", B[i]);
    }
}


void max(int array[],int *k,int n){
    int i;
    printf("n je %d\n",n);
    for (i = 0; i < n; i++)
    {
        if (array[i] > *k) {
            *k = array[i];
        }
    }
}

int main(int brArg,char *arg[])
{

    FILE *ulaz;
    ulaz = fopen(arg[1], "r");

    int array[100];
    int i=0,j,k=0,n,x,z;


    while(fscanf(ulaz, "%d", &array[i])!=EOF)i++;

    fclose(ulaz);
    n=i;

    max(array,&k,n);
    printf("Max je %d\n",k);
    CountingSort(array,k,n);
    return 0;
}

我没有错误,但是当我启动程序时,我得到了Segmentation fault错误。请帮忙! (不要读这个机器人要求我写一些更多的细节,但我没有,所以我只是写一些随机的话,所以我可以发表我的问题,希望得到一个答案)

3 个答案:

答案 0 :(得分:2)

问题是你的计数排序的实现是不正确的:它使用数组就好像它们是基于一的,而在C中它们是从零开始的。

仔细浏览循环并修复使用for循环1..k的所有情况,而不是正确的0..k-1,代码开始正常工作:

int i, j;
int B[100], C[1000];
for (i = 0; i <= k; i++){
     C[i] = 0;
}
for (j = 0; j < n; j++){
     C[array[j]]++;
}
for (i = 1; i <= k; i++){
     C[i] += C[i-1];
}
for (j = 0; j < n; j++) {
  B[--C[array[j]]] = array[j];
}
printf("The Sorted array is : ");
for (i = 0; i < n; i++) {
   printf("%d ", B[i]);
}

Demo.

注意:我修改了一些操作以使用C风格的复合赋值和递增/递减,例如C[array[j]]++取代C[array[j]] = C[array[j]] + 1等。

答案 1 :(得分:0)

问题最有可能在这里

int B[100], C[1000]; // C has space for numbers up to 999
...
for (i = 1; i <= k; i++)
    C[i] = C[i] + C[i-1]; // adding up till C[k] == sum(array)
for (j = 0; j < n; j++)
    B[C[array[j]]] = array[j]; // B has space up to 99, but C[k] is sum(array)

因此,您为C预留了最高值为999的空间,但在B中您假设所有输入值的总和小于100 ...

问题的解决方法是首先探测输入数组并获得所有输入值的最大值和总和(如果范围可能为负,则为最小值)并相应地分配空间

编辑:您可能需要j < n而不是j <= n

答案 2 :(得分:0)

添加到dasblinkenlight的现场答案:

您的输入数据是否保证在[0, 999]范围内?如果不是,很明显可能并且将会发生分段错误。假设array的最大值为1000. C被声明为

int C[1000];

表示C的有效索引为0, 1, 2, ... 999。但是,在某些时候,您将拥有以下内容:

C[array[j]] = ... /* whatever */

其中array[j] > 999所以你将尝试越界内存访问。解决方案很简单:探测array的最大值,并通过malloc使用动态内存分配:

/* assuming k is the maximum value */
int * C = malloc((k + 1) * sizeof(int));

注意:对此的替代方法,即使C的所有元素都等于0,也会使初始化循环无效,将动态使用calloc将内存设置为0。

// allocate C with elements set to 0
int * C = calloc(k + 1, sizeof(int);

另一个重要因素是运行索引的范围:您似乎忘记了C中的数组是从0开始编制索引的。要遍历长度为K的数组,您可以执行以下操作:

for (i = 0; i < K; ++i)
{ 
    processArray(array[i]); 
}

而不是

for (i = 1; i <= K; ++i)
{
    processArray(array[i]);
}