简体   繁体   中英

Understanding Heaps

Every reference I look at to learn about heaps says that the sift_down approach to building heaps is the ideal way, but does this mean that it is still possible to build a heap using sift_up? If so, why is sift_down preferred? I'm trying to get a better understanding of these types of things for an algorithms course I am taking. I'd like to try to implement a build_heap function that uses sift_up, but so far I haven't had any luck, though I have managed to get it to work using sift_down.

Any ideas, suggestions, or references that anyone could share? Here's a few functions I'm struggling with at the moment:

#include <stdio.h>

void bottom_up_heapsort(int*, int);
void heapsort(int*, int);
void sift_up(int*, int);
void sift_down(int*, int);
void build_max_heap(int*, int); 
void bottom_up_build_max_heap(int*, int);
void swap(int*, int*);

int heapsize;

int main() {
    int A[] = { 7, 12, 1, -2, 0, 15, 4, 11, 9 };
    int B[] = { 7, 12, 1, -2, 0, 15, 4, 11, 9 };
    int i;
    int size = 9;

    printf("Unsorted array: \n");
    for(i = 0; i < size; i++) {
        printf(" %d ", A[i]);
    }

    heapsort(A, size); 
    printf("\n");

    printf("Sorted array: \n");
    for(i = 0; i < size; i++) {
        printf(" %d ", A[i]);
    }
    printf("\n");

    printf("----------------------------------\n");
    printf("Unsorted array for bottom up: \n");
    for(i = 0; i < size; i++) {
        printf(" %d ", B[i]);
    }

    bottom_up_heapsort(B, size); 
    printf("\n");

    printf("Sorted array: \n");
    for(i = 0; i < size; i++) {
        printf(" %d ", B[i]);
    }
    printf("\n");

    return 0;
}

void bottom_up_heapsort(int* arr, int len) {
    int i;

    bottom_up_build_max_heap(arr, len);
    for(i = len-1; i >= 1; i--) {
        sift_up(arr, len);
        heapsize--;
        swap(&arr[i], &arr[0]);
    }
}

void heapsort(int* arr, int len) {
    int i;

    build_max_heap(arr, len);

    for(i = len-1; i >= 1; i--) {
        swap(&arr[0], &arr[i]); // move arr[0] to its sorted place
        heapsize = heapsize - 1;
        sift_down(arr, 0);  // repair the heap
    }
}

void sift_down(int* arr, int i) {
    int l = 2*i, r = 2*i+1;
    int largest;

    if(l < heapsize && arr[l] > arr[i]) {
        largest = l;
    }
    else {
        largest = i;
    }

    if(r < heapsize && arr[r] > arr[largest]) {
        largest = r;
    }

    if(largest != i) {
        swap(&arr[i], &arr[largest]);
        sift_down(arr, largest);
    }
}

void sift_up(int* arr, int i) {
    if(i == 1) return; // at the root

    if(arr[i] > arr[i/2]) {
        swap(&arr[i], &arr[i/2]);
        sift_up(arr, i/2);
    }
}

void bottom_up_build_max_heap(int* arr, int len) {
    heapsize = len;
    int i;
    for(i = 0; i <= len; i++) {
        sift_up(arr, i);
    }
}

void build_max_heap(int* arr, int len) {
    heapsize = len;
    int i;
    for(i = len/2; i >= 0; i--) {
        // invariant: arr[k], i < k <= n are roots of proper heaps
        sift_down(arr, i);
    }
}

void swap(int* a, int* b) {
    int temp = *a;
    *a = *b;
    *b = temp;
}

You should be able to do

for (int i = 1; i <= n; i++) sift_up(heap, i);

which is equivalent to inserting the elements one by one. The worst-case running time is Theta(n log n), since in the worst case each new element must be sifted all the way to the root. This running time is worse than that of the sift_down heapify, namely, Theta(n). The difference is that sift_down can move the majority of elements only a couple levels down, while sift_up can move the majority of elements log n levels up.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM