堆排序无法正常工作

时间:2015-06-22 11:02:41

标签: c sorting heapsort

我正在用C语言编写排序应用程序,因为我有一个算法(堆排序)。这是我的代码:

void heap_sort(int *array, int size) {
    int temp;

    heap_build(array, size);

    for(int i = size; i>1; i--) {
        temp = array[i];
        array[i] = array[1];
        array[1] = temp;
        size--;
        heap_heapify(array, size, 1);
    }
}

void heap_build(int *array, int size) {
    for(int i = size / 2; i > 0; i--)
        heap_heapify(array, size, i);
}

void heap_heapify(int *array, int size, int i) {
    int largest, temp, 
        l = 2 * i, r = (2 * i) + 1;

    if(l <= size && array[l] > array[i])
        largest = l;
    else 
        largest = i;

    if(r <= size && array[r] > array[largest])
        largest = r;

    if(largest != i) {
        temp = array[largest];
        array[largest] = array[i];
        array[i] = temp;
        heap_heapify(array, size, largest);
    }
}

结果是例如:

-22
-33686019 // the range is <-100, 100>
-71
-68
-59
-17
-8
43
59
82

你怎么看,数字没有正确排序,我有一个有线号码(总是在数组[1]中)。

1 个答案:

答案 0 :(得分:1)

在评论中,您提到您在1..N区间使用数组索引来获取大小为N+1的数组,但传入的大小为N+1。如果这是真的,那么max-heapify()中就会出现一个错误:如果sizeN+1,则您可以访问的最后一个位置是N,而不是{{1}因此,您必须将比较更改为N+1(对于l < size也是如此):

r

或者,如果您希望代码尽可能接近CLRS,只要您将void heap_heapify(int *array, int size, int i) { int largest, temp, l = 2 * i, r = (2 * i) + 1; if(l < size && array[l] > array[i]) largest = l; else largest = i; if(r < size && array[r] > array[largest]) largest = r; if(largest != i) { temp = array[largest]; array[largest] = array[i]; array[i] = temp; heap_heapify(array, size, largest); } } 作为大小而不是<=传递,就可以使用N(所以,你分配了一个N+1元素数组,但是你传递了N+1作为大小,所以事情排成一行。)

[旁注:我一直在告诉我,CLRS使用从1开始索引的数组。这在编写基于伪代码的实际代码时总会造成麻烦。)

N中也是如此,要么将heap_sort()作为N元素数组的大小传递,要么将N+1初始化为i:< / p>

size-1

这是一个包含工作代码的完整程序:

void heap_sort(int *array, int size) {
    int temp;

    heap_build(array, size);

    for(int i = size-1; i>1; i--) {
        temp = array[i];
        array[i] = array[1];
        array[1] = temp;
        size--;
        heap_heapify(array, size, 1);
    }
}

打印:

#include <stdio.h>

void heap_build(int *array, int size);
void heap_heapify(int *array, int size, int i);

void heap_sort(int *array, int size) {
    int temp;

    heap_build(array, size);

    for(int i = size-1; i>1; i--) {
        temp = array[i];
        array[i] = array[1];
        array[1] = temp;
        size--;
        heap_heapify(array, size, 1);
    }
}

void heap_build(int *array, int size) {
    for(int i = size / 2; i > 0; i--)
        heap_heapify(array, size, i);
}

void heap_heapify(int *array, int size, int i) {
    int largest, temp, 
        l = 2 * i, r = (2 * i) + 1;

    if(l < size && array[l] > array[i])
        largest = l;
    else 
        largest = i;

    if(r < size && array[r] > array[largest])
        largest = r;

    if(largest != i) {
        temp = array[largest];
        array[largest] = array[i];
        array[i] = temp;
        heap_heapify(array, size, largest);
    }
}

int main(void) {
    int arr[] = { 0, -22, 2, -33, 82, 71, 82, 0, -68, -59, -17, -8, 43, 59, -100 };

    heap_sort(arr, sizeof(arr)/sizeof(arr[0]));

    for (int i = 0; i < sizeof(arr)/sizeof(arr[0]); i++) {
        printf("%d\n", arr[i]);
    }

    return 0;
}

请注意,第一个元素永远不会被排序;因为你使用了索引0 -100 -68 -59 -33 -22 -17 -8 0 2 43 59 71 82 82 ,所以你基本上忽略了元素0.一个快速的黑客是在数组开始之前传入指向一个元素的指针,但这很难看,而且UB(指针算法只有效)如果结果指针引用了数组中的元素,或者引用了结尾的一个元素。)

所以我建议重构代码并忘记基于1的索引。这可以通过调整公式来计算节点的左子节点和调整循环条件来完成:

1..N

与先前版本的不同之处在于:

  1. #include <stdio.h> void heap_build(int *array, int size); void heap_heapify(int *array, int size, int i); void heap_sort(int *array, int size) { int temp; heap_build(array, size); for(int i = size-1; i > 0; i--) { temp = array[i]; array[i] = array[0]; array[0] = temp; size--; heap_heapify(array, size, 0); } } void heap_build(int *array, int size) { for(int i = size/2; i >= 0; i--) heap_heapify(array, size, i); } void heap_heapify(int *array, int size, int i) { int largest, temp, l = i*2+1, r = l+1; if (l < size && array[l] > array[i]) largest = l; else largest = i; if (r < size && array[r] > array[largest]) largest = r; if (largest != i) { temp = array[largest]; array[largest] = array[i]; array[i] = temp; heap_heapify(array, size, largest); } } int main(void) { int arr[] = { 0, -22, 2, -33, 82, 71, 82, 0, -68, -59, -17, -8, 43, 59, -100 }; heap_sort(arr, sizeof(arr)/sizeof(arr[0])); for (int i = 0; i < sizeof(arr)/sizeof(arr[0]); i++) { printf("%d\n", arr[i]); } return 0; } 中,循环条件变为heap_sort
  2. i > 0中,循环条件变为heap_build()
  3. i >= 0中,左边的孩子是heap_heapify()而不是2*i+12*ir