分段错误:11,当我从“算法简介”一书中测试heapsort代码时

时间:2016-08-06 09:35:48

标签: c algorithm sorting heapsort

我在C语言的'Introduction of Algorithms'一书中执行了heapsort的伪代码,并发生了错误:分段错误:11。内存溢出有问题吗?

#define LEFT(i) 2*i;
#define RIGHT(i) 2*i+1;
#define PARENT(i) i/2;

/************************************************/
/*heap_sort -- stable
*In order to easily determine the relationship of index between parent node and child nodes,
*available index of arr starts from 1.
*/
/************************************************/

/*
    Available index of arr starts from 1.
    Length represents the last element's index.
    Heap_size is biggest range in arr.
*/
typedef struct {
    int heap_size;
    int length;
    int *arr;
} heap;

/*
    Node i's left_child tree and right_child tree are all max heap.
    This function put node i's value into proper position in oder to keep a max heap.
*/
void max_heapify(heap h, int i) {
    int *arr = h.arr;
    int left = LEFT(i);
    int right = RIGHT(i);
    int largest = i;

    if (arr[left] > arr[i] && left <= h.heap_size)
        largest = left;
    if (arr[right] > arr[largest] && right <= h.heap_size)
        largest = right;

    if (largest != i) {
        exchange(h.arr + i, h.arr + largest);
        max_heapify(h, largest);
    }

    return;
}

/*
    Build a max heap.
*/
void build_max_heap(heap h) {
    h.heap_size = h.length;
    for (int i = h.length / 2; i > 0; i--)  //leaf nodes need not to call max_heapify
        max_heapify(h, i);
    return;
}

void heap_sort(heap h) {
    build_max_heap(h);
    int *arr = h.arr;
    for (int i = h.length; i > 1; i--) {
        exchange(arr + 1, arr + i);
        h.heap_size--;
        max_heapify(h, 1);
    }
    return;
}

int main() {
    int arr[] = {1,4,9,0,2,1,6,2};
    int num = sizeof(arr) / sizeof(int);
    heap h = {0, num - 1, arr};
    heap_sort(h);
    for (int i = 1; i < num; i++) {
        printf("%d,", arr[i]);
        }

    return 0;
}

最大堆是一个二叉树,其中节点的值大于其左右子节点的值。

1 个答案:

答案 0 :(得分:0)

max_heapify()函数中,首先需要检查leftright是否仍在界限内 - 即它们是<= h.heap_size,并且只有在它们受到约束时,那么您需要评估arr[left]arr[right]的值。但是,你正在做相反的事情。因此,当尝试访问arr[left]arr[right]时尝试超出范围时,程序会崩溃。这可以通过更改if语句中的条件顺序来解决,如下所示。

void max_heapify(heap h, int i) {
    int *arr = h.arr;
    int left = LEFT(i);
    int right = RIGHT(i);
    int largest = i;

    /* ISSUE: You are evaluating first, checking bounds second */   
    /* if (arr[left] > arr[i] && left <= h.heap_size) */ 

    /* Right way: Check bounds first, evaluate second */
    if (left <= h.heap_size && arr[left] > arr[i]) /* Right */
        largest = left;

    /* ISSUE: You are evaluating first, checking bounds second */ 
    /* if (arr[right] > arr[largest] && right <= h.heap_size) */

    /* Right way: Check bounds first, evaluate second */
    if (right <= h.heap_size && arr[right] > arr[largest])
        largest = right;

    if (largest != i) {
        exchange(h.arr + i, h.arr + largest);
        max_heapify(h, largest);
    }

    return;
}

以上更改应解决程序崩溃问题。

但是你的代码中还有一个问题 - 与程序崩溃无关,但却给你错误的结果。您还需要在h.heap_size = h.length功能中设置heap_sort()。这是因为,由于您按值传递了堆h,因此在h.heap_size = h.length;函数中设置build_max_heap()不会影响h.heap_sizeheap_sort()的值功能。您需要再次在heap_sort()函数中明确地执行此操作。

void heap_sort(heap h)
{
    build_max_heap(h);
    int *arr = h.arr;
    h.heap_size = h.length; /* This statement REQUIRED here */
    for (int i = h.length; i > 1;  i--)
    {
            exchange(arr + 1, arr + i); 
            h.heap_size = h.heap_size - 1;
            max_heapify(h, 1); 
    }

    return;
}