桶排序+插入排序算法中的分段错误

时间:2017-09-10 14:25:01

标签: c algorithm sorting

我想知道为什么我为桶排序实现的算法会因此而出现Segmentation fault。似乎实现中的所有内容都运行良好,但可能有一些变量n应该是n + 1或其他;我在解决这个问题时遇到了一些困难。

我正在根据this video中描述的内容实现它。

#include <stdio.h>
#include <stdlib.h>

void insertion(int * array, int n){
    // insertion sort
    int i = 1, j = 0, temp;
    while(i < n){
        j = i;
        while(j > 0 && array[j-1] > array[j]){
            temp = array[j-1];
            array[j-1] = array[j];
            array[j] = temp;
            --j;
        }
        ++i;
    }
}

void bucket(int * array, int n){
    int max,i,j,k,size, div, pos;
    int ** buckets, *bucket_position;

    //Find maximum value in array
    max = array[0];
    for(i=0;i<n;++i) if( max < array[i] ) max = array[i];

    //Determine amount of buckets and creates them
    size = max / n;
    buckets = (int**) malloc(sizeof(int*) * size);
    for(i=0;i<size;++i){
        buckets[i] = (int*) malloc(sizeof(int) * max);
    }
    bucket_position = (int*) malloc(sizeof(int) * size);
    for(i=0;i<size;++i) bucket_position[i] = 0;

    //Copy array values into the buckets
    div = (max+1) / size;
    if( (max+1) % size ) ++div;
    for(i=0;i<n;++i){
        pos = array[i] / div;
        buckets[pos][bucket_position[pos]] = array[i];
        ++bucket_position[pos];
    }

    //Take values out of the buckets into the array
    k = 0;  
    for(i=0;i<size;++i){
        for(j=0;j<=bucket_position[i];++j){
            array[k] = buckets[i][j];
            ++k;
        }
    }

    //Do insertion sort over the array
    insertion(array,n);
}

int main(){
    int array[5] = {24354,95023,439052,934851};
    int n = 5;
    bucket(array,n);
    return 0;
}

程序输出是分段错误而不是排序数组。

2 个答案:

答案 0 :(得分:2)

您希望使用n == 5元素对数组进行排序,其最大值为:

max == 934851

然后你计算桶的nuber:

size = max / n == 186970

现在你尝试为186970个桶分配内存,每个桶都有容纳934851个元素的容量:

buckets = (int**) malloc(sizeof(int*) * size);

for (i = 0; i < size; ++i) {
    buckets[i] = (int*) malloc(sizeof(int) * max);
}

这大约是651千兆字节。由于有如此多的大型分配,系统很可能无法提供更多内存。因此,您应该检查malloc返回的指针是否为NULL。这就是发生的事情:您的数组索引是合法的,但动态分配的数组是NULL

当然,您不需要那么多内存来排序五个元素。对于这么小的阵列,你根本不需要使用桶;直接使用插入排序。

对于较大的数组,根据元素数量而不是最大值来确定存储桶的数量。在最坏的情况下,所有元素都进入一个桶,然后将有n个元素。因此,您不需要max来确定此处的大小。

但是,您应该使用您的程序没有的maxmin来计算存储区索引:

index = (a[i] - min) * nbuckets / (max + 1 - min)

请注意此处可能的算术溢出。 (+ 1确保最大元素不会获得无效索引n。)

答案 1 :(得分:0)

此代码

k = 0;  
for(i=0;i<size;++i){
    for(j=0;j<=bucket_position[i];++j){
        array[k] = buckets[i][j];
        ++k;
    }
}

是个问题。

你会多次增加k,从而在array之外写字。请记住,k的有效范围仅为0到4。

而不是

for(j=0;j<=bucket_position[i];++j){
        ^^^^

也许你想要

for(j=0;j<bucket_position[i];++j){
        ^^^

即。 <代替<=,以便您不会在每个循环中增加k