最小堆结构中的Sentinel控制循环

时间:2013-07-03 21:03:17

标签: c heap sentinel

我的堆定义如下:

文件:heap.h

#ifndef __HEAP__
#define __HEAP__

typedef struct heap heap;

heap* heap_new();
void  heap_delete(heap* h);
void  heap_insert(heap* h, int x);
void  heap_delete_last(heap* h);

#endif

文件:heap.c

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

#ifndef MIN_SIZE
#define MIN_SIZE 4
#endif

struct heap {
    int* v;
    int n;
    int size;
};


// ---------------------------------------------------------------------
// expand
// ---------------------------------------------------------------------
// expand heap size by 50%
static void expand(heap* h) {
    h->size += h->size/2;
    h->v = realloc(h->v, h->size*sizeof(int));
}


// ---------------------------------------------------------------------
// heap_new
// ---------------------------------------------------------------------
// create new empty heap object
heap* heap_new() {
    heap* h = malloc(sizeof(heap));
    h->size = MIN_SIZE;
    h->v = malloc(h->size*sizeof(int));
    h->n = 0;
    return h;
}


// ---------------------------------------------------------------------
// heap_delete
// ---------------------------------------------------------------------
// delete heap object
void heap_delete(heap* h) {
    free(h->v);
    free(h);
}


// ---------------------------------------------------------------------
// heap_dump
// ---------------------------------------------------------------------
// dump heap content to stdio
void heap_dump(heap* h) {
    int i;
    for (i=0; i<=h->n; i++)
        printf("[%d] %d\n", i, h->v[i]);
}


// ---------------------------------------------------------------------
// heap_check
// ---------------------------------------------------------------------
// test heap correctness
int heap_check(heap* h) {
    int i;
    for (i=1; i<=h->n; i++)
        if (  i   >  1    && h->v[i] < h->v[i/2]  ) return 0;
        if (2*i   <= h->n && h->v[i] > h->v[2*i]  ) return 0;
        if (2*i+1 <= h->n && h->v[i] > h->v[2*i+1]) return 0;
    return 1;
}


// ---------------------------------------------------------------------
// heap_insert
// ---------------------------------------------------------------------
// insert key into heap
void heap_insert(heap* h, int x){
    if (++h->n == h->size) expand(h);
    int *v = h->v;
    unsigned long c = h->n, p = c >> 1;
    while (p > 0 && v[p] > x) {
        v[c] = v[p];
        c = p;
        p >>= 1;
    }
    v[c] = x;
}


// ---------------------------------------------------------------------
// heap_delete_last
// ---------------------------------------------------------------------
// remove last heap element
void  heap_delete_last(heap* h) {
    if (h->n > 0) h->n--;
}

我的问题非常简单。将注意力集中在heap_insert函数上:有一个包含两个测试p > 0 && v[p] > x的循环。考虑到这个循环,有没有办法用哨兵控制它并避免第二次测试?我从来没有遇到过这样的情况,无法猜出哨兵使用的是什么样的。提前谢谢。

我举一个哨兵控制循环的例子:

    /*Returns 0 if x doesn't exist in v, 1 otherwise */
int find_value(int *v, int n, int x) {
    int i;
            //loop with 2 tests
    for (i=0; i<n; i++)
        if (v[i]==x) return 1;
    return 0;
}
带有哨兵的

find_value功能(避免一次测试):

 int find_value(int *v, int n, int x) {
    int i=0;
    if(v[n-1] == x) return 1; //x is in the last spot
    int last = v[n-1]; //save last element
    v[n-1] = x; //one x element in v at least (test [i<n] id unnecessary)
    while(v[i++] != x); 
    v[n-1] = last; 

    return i < n-1; 
}

0 个答案:

没有答案