c - 如何修改最大堆中值的优先级?

标签 c binary-heap max-heap

我正在写一个最大堆,它可以改变优先级/值。但是,我很难理解我的代码有什么问题。 我已将此作为引用:ref 这是我的代码(我隐藏了一些功能,因为它不是这里的重点)

static void swap(MAX_HEAP *heap, int i, int j);
static void swim(MAX_HEAP *heap, int k);
static void sink(MAX_HEAP *heap, int k);

void swap(MAX_HEAP *heap, int i, int j) {
    HEAP_ELEM s;
    int k;

    s = heap->binary_heap[i];
    k = heap->keys[s.fu];

    heap->binary_heap[i] = heap->binary_heap[j];
    heap->keys[k] = heap->keys[heap->binary_heap[j].fu];

    heap->keys[heap->binary_heap[j].fu] = k;
    heap->binary_heap[j] = s;
}

void swim(MAX_HEAP *heap, int k) {
    int m;
    m = k / 2.0;
    while (k > 1 && heap->binary_heap[m].priority < heap->binary_heap[k].priority) {
        swap(heap, k, m);
        k = m;
        m = k / 2.0;
    }
}

void sink(MAX_HEAP *heap, int k) {
    int j;
    while (2 * k <= heap->n) {
        j = 2 * k;
        if (j < heap->n && heap->binary_heap[j].priority < heap->binary_heap[j + 1].priority)
            j++;
        if (!(heap->binary_heap[k].priority < heap->binary_heap[j].priority))
            break;
        swap(heap, k, j);
        k = j;
    }
}

MAX_HEAP *create_maxheap(int capacity) {
    int i;

    MAX_HEAP *ret;
    ret = (MAX_HEAP*) malloc(sizeof (MAX_HEAP));
    ret->n = 0;
    ret->binary_heap = (HEAP_ELEM*) malloc(sizeof (HEAP_ELEM) * (capacity + 1));
    ret->binary_heap[0].fu = 0;
    ret->binary_heap[0].priority = 0;
    ret->max = capacity;

    ret->keys = (int*) malloc(sizeof (int) * (capacity + 1));
    for (i = 0; i <= capacity + 1; i++) {
        ret->keys[i] = -1;
    }

    return ret;
}

HEAP_ELEM get_maxheap(MAX_HEAP *heap) {
    HEAP_ELEM ret;
    if (heap->n == 0) {
        return;
    }
    ret = heap->binary_heap[1];

    heap->keys[ret.fu] = -1;

    swap(heap, 1, heap->n);
    heap->n--;
    sink(heap, 1);

    return ret;
}

void insert_maxheap(MAX_HEAP *heap, int fu, int p) {
    if (heap->n + 1 >= heap->max) {
        int i;
        heap->max *= 2;
        heap->keys = (int*) realloc(heap->keys, sizeof (int) * (heap->max + 1));
        heap->binary_heap = (HEAP_ELEM*) realloc(heap->binary_heap, sizeof (HEAP_ELEM) * (heap->max + 1));
        for (i = heap->n+1; i < heap->max + 1; i++) {
            heap->keys[i] = -1;
        }
    }

    heap->n++;
    heap->binary_heap[heap->n].fu = fu;
    heap->binary_heap[heap->n].priority = p;
    heap->keys[fu] = heap->n;
    swim(heap, heap->n);
}

void modify_maxheap(MAX_HEAP *heap, int fu, int p) {
    int i;
    i = heap->keys[fu];
    int old;

    if (i == -1) {
        insert_maxheap(heap, fu, p);
        return;
    }

    old = heap->binary_heap[i].priority;

    heap->binary_heap[i].fu = fu;
    heap->binary_heap[i].priority = p;
    heap->keys[fu] = i;

    if (old < p) {
        /* we need to bubble up*/
        swim(heap, i);
    } else if (old > p) {
        //we need to bubble down
        sink(heap, i);
    }
}

当我执行以下操作时,结果很糟糕……这里有什么问题吗?例如……

int main(int argc, char** argv) {
    MAX_HEAP *heap, *heap2;
    HEAP_ELEM he;
    heap = create_maxheap(3);

    modify_maxheap(heap, 1, 7);
    modify_maxheap(heap, 2, 10);
    modify_maxheap(heap, 3, 78);
    modify_maxheap(heap, 4, 3);
    modify_maxheap(heap, 5, 45);

    printf("heap 1\n\n");
    while(heap->n > 0) {
        he = get_maxheap(heap);
        printf("..fu: %d; value: %d\n", he.fu, he.priority);
    }
    printf("max size of heap1: %d\n", heap->max);
    printf("\n\n");

    heap2 = create_maxheap(10);

    modify_maxheap(heap2, 3, 90);
    modify_maxheap(heap2, 1, 7);    
    modify_maxheap(heap2, 2, 10);
    modify_maxheap(heap2, 3, 9);
    modify_maxheap(heap2, 3, 92);
    modify_maxheap(heap2, 4, 3);
    modify_maxheap(heap2, 3, 90);
    modify_maxheap(heap2, 1, 99);
    modify_maxheap(heap2, 5, 45);
    modify_maxheap(heap2, 1, 89);

    printf("heap 2\n\n");
     while(heap2->n > 0) {
        he = get_maxheap(heap2);
        printf("fu: %d; value: %d\n", he.fu, he.priority);
    }


    return (EXIT_SUCCESS);
}

请注意,我正在使用一个数组来存储 HEAP_ELEM 的索引,以便了解 HEAP_ELEM 的位置(它的主键是“fu”并更改其优先级。这是我的输出:

heap 1

..fu: 3; value: 78
..fu: 5; value: 45
..fu: 2; value: 10
..fu: 1; value: 7
..fu: 4; value: 3
max size of heap1: 6


heap 2

fu: 1; value: 99
fu: 3; value: 90
fu: 1; value: 89
fu: 5; value: 45
fu: 4; value: 3

最佳答案

我已经更改了我的 modify_maxheap 函数并且它起作用了:

void modify_maxheap(MAX_HEAP *heap, int fu, int p) {
    int i;
    i = heap->keys[fu];

    if (i == -1) {
        insert_maxheap(heap, fu, p);
        return;
    }    

    heap->binary_heap[i].priority = p;
    swim(heap, i);
    sink(heap, i);
}

原因是我们必须在任何修改的情况下向上冒泡和向下冒泡以保证堆条件。我希望它可以作为某人的基础。

关于c - 如何修改最大堆中值的优先级?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36418154/

相关文章:

c - 编译错误 "SIG_BLOCK undeclared"是什么意思?

c - BST 中的顺序后继者

c - 可执行文件中的数据位于奇怪的位置

c - Material 着色不起作用

algorithm - Heapsort:为什么倒数第二层最右边的节点位于索引 n/2-1 处?

algorithm - 修改heapsort算法,一次从堆中取出k个元素

python - 如何在python中获取最大堆

algorithm - 有没有更好的方法来计算文件中所有符号的频率?

algorithm - 试图了解 max heapify

c++ - 排序函数和优先级队列中的比较器 C++