最小堆

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

struct heap_elem
{
    int data;
    unsigned heap_idx;
    /* data */
};


typedef struct min_heap
{
    struct heap_elem** data;
    int element_num;
    int size;
    /* data */
} min_heap_t;

static int min_heap_elem_greater(struct heap_elem* elem1, struct heap_elem* elem2)
{
    return elem1->data > elem2->data;
}

static void min_heap_shift_up(min_heap_t* heap, unsigned idx, struct heap_elem* data)
{
    /* 1.先计算出父节点的下标 */
    unsigned parent = (idx - 1) / 2;
    /* 1. 保证idx>0,才能确保parent是有效的下标
       2. 只有当parent下标的值大于要插入的值才需要继续向上找 
     */
    while (idx && min_heap_elem_greater(heap->data[parent], data))
    {
        /* code */
        heap->data[idx] = heap->data[parent];
        heap->data[idx]->heap_idx = idx;
        idx = parent;
        parent = (idx - 1) / 2;
    }

    heap->data[idx] = data;
    heap->data[idx]->heap_idx = idx;
}

static int min_heap_reserve(min_heap_t* heap, unsigned element_num)
{
    if (heap->size < element_num) {
        unsigned s = heap->size == 0 ? 8 : 2 * heap->size;
        struct heap_elem** p = (struct heap_elem**)realloc(heap->data, s * sizeof(struct heap_elem*));
        if (p == NULL) {
            return -1;
        }
        heap->data = p;
        heap->size = s;
    }
    return 0;
}

int min_heap_push(min_heap_t* heap, struct heap_elem* data)
{
    if (min_heap_reserve(heap, heap->element_num + 1)) {
        return -1;
    }
    min_heap_shift_up(heap, heap->element_num++, data);
    return 0;
}

static int min_heap_shift_down(min_heap_t* heap, unsigned idx, struct heap_elem* data)
{
    unsigned min_child = (idx + 1) * 2;
    while (min_child <= heap->element_num) {
        min_child -= min_child == heap->element_num || min_heap_elem_greater(heap->data[min_child], heap->data[min_child - 1]);
        // 如果当前的元素大于要插入的元素,直接break,说明已经找到了
        if (!min_heap_elem_greater(data, heap->data[min_child])) {
            break;
        }
        heap->data[idx] = heap->data[min_child];
        heap->data[idx]->heap_idx = idx;
        idx = min_child;
        min_child = (idx + 1) * 2;
    }
    min_heap_shift_up(heap, idx, data);
}

struct heap_elem* min_heap_pop(min_heap_t* heap)
{
    struct heap_elem* ptr = 0;
    if (heap->element_num) {
        ptr = *heap->data;
        min_heap_shift_down(heap, 0, heap->data[--heap->element_num]);
        ptr->heap_idx = -1;
    }

    return ptr;
}
posted @ 2024-11-19 11:22  cockpunctual  阅读(8)  评论(0)    收藏  举报