我想知道为什么我为桶排序实现的算法会因此而出现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;
}
程序输出是分段错误而不是排序数组。
答案 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
来确定此处的大小。
但是,您应该使用您的程序没有的max
和min
来计算存储区索引:
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
。