美文网首页
c语言最大最小堆(heap)

c语言最大最小堆(heap)

作者: help_youself | 来源:发表于2019-06-20 14:37 被阅读0次

 代码是从[1]中copy的,以后用到堆的地方,就不用自己写了。
heap.h

#ifndef HEAP_H
#define HEAP_H
#ifdef __cplusplus
extern "C" {
#endif
typedef struct heap_s heap_t;
struct heap_s
{
    void **array;
    /* size of array */
    unsigned int size;
    /* items within heap */
    unsigned int count;
    /**  user data */
    const void *udata;
    int (*cmp) (const void *, const void *, const void *);
};

/**
 * Create a new heap and initialise it.
 *
 * malloc()s space for heap.
 *
 * @param[in] cmp Callback used to determine the priority of the item
 * @param[in] udata User data passed through to cmp callback
 * @return initialised heap */
heap_t *heap_new(int (*cmp) (const void *,
                             const void *,
                             const void *udata),
                 const void *udata);

/**
 * Initialise a heap. Use memory provided by user.
 *
 * No malloc()s are performed.
 *
 * @param[in] cmp Callback used to determine the priority of the item
 * @param[in] udata User data passed through to cmp callback
 * @param[in] array Array used for heap
 * @param[in] size The size of the array */
void heap_init(heap_t* h,
               int (*cmp) (const void *,
                           const void *,
                           const void *udata),
               const void *udata,
               void **array,
               unsigned int size);

/**
 * Free memory held by heap */
void heap_free(heap_t * hp);

/**
 * Add item to heap.
 *
 * Ensures that heap can hold item.
 * malloc() possibly called.
 *
 * @param[in] item Item to be added to the heap
 * @return 0 on success; -1 on error */
int heap_offer(heap_t * hp, void *item);

/**
 * Add item to heap.
 *
 * An error will occur if there isn't enough space in the heap for this item.
 * no malloc()s called.
 *
 * @param[in] item Item to be added to the heap
 * @return 0 on success; -1 on error */
int heap_offerx(heap_t * hp, void *item);

/**
 * Remove the top value from this heap.
 * @return top item of the heap */
void *heap_poll(heap_t * hp);

/**
 * @return top item of the heap */
void *heap_peek(heap_t * hp);

/**
 * Clear all items from the heap.
 * Does not free items. Only use if item memory is managed outside of heap */
void heap_clear(heap_t * hp);

/**
 * @return number of items in heap */
int heap_count(heap_t * hp);

/**
 * @return size of array */
int heap_size(heap_t * hp);

/**
 * Remove item from heap
 *
 * @param[in] item Item that is to be removed
 * @return item to be removed; NULL if item does not exist */
void *heap_remove_item(heap_t * hp, const void *item);

/**
 * The heap will remove this item
 *
 * @param[in] item Item to be removed
 * @return 1 if the heap contains this item; 0 otherwise */
int heap_contains_item(heap_t * hp, const void *item);
#ifdef __cplusplus
}
#endif
#endif /* HEAP_H */

heap.c


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

#include "heap.h"

#define DEFAULT_CAPACITY 13

static int __child_left(const int idx)
{
    return idx * 2 + 1;
}

static int __child_right(const int idx)
{
    return idx * 2 + 2;
}

static int __parent(const int idx)
{
    return (idx - 1) / 2;
}

void heap_init(heap_t* h,
               int (*cmp) (const void *,
                           const void *,
                           const void *udata),
               const void *udata,
               void **array,
               unsigned int size
               )
{
    h->cmp = cmp;
    h->udata = udata;
    h->size = size;
    h->count = 0;
    h->array = array;
}

heap_t *heap_new(int (*cmp) (const void *,
                             const void *,
                             const void *udata),
                 const void *udata)
{
    heap_t *h = malloc(sizeof(heap_t));

    if (!h)
        return NULL;

    void** array = malloc(sizeof(void *) * DEFAULT_CAPACITY);

    if (!array)
    {
        free(h);
        return NULL;
    }

    heap_init(h, cmp, udata, array, DEFAULT_CAPACITY);

    return h;
}

void heap_free(heap_t * h)
{
    free(h->array);
    free(h);
}

/**
 * @return 0 on success; -1 otherwise */
static int __ensurecapacity(heap_t * h)
{
    if (h->count < h->size)
        return 0;

    h->size *= 2;

    void **new_array = malloc(sizeof(void *) * h->size);

    if (!new_array)
        return -1;

    /* copy old data across to new array */
    unsigned int i;
    for (i = 0; i < h->count; i++)
        new_array[i] = h->array[i];

    /* swap arrays */
    free(h->array);
    h->array = new_array;
    return 0;
}

static void __swap(heap_t * h, const int i1, const int i2)
{
    void *tmp = h->array[i1];

    h->array[i1] = h->array[i2];
    h->array[i2] = tmp;
}

static int __pushup(heap_t * h, unsigned int idx)
{
    /* 0 is the root node */
    while (0 != idx)
    {
        int parent = __parent(idx);

        /* we are smaller than the parent */
        if (h->cmp(h->array[idx], h->array[parent], h->udata) < 0)
            return -1;
        else
            __swap(h, idx, parent);

        idx = parent;
    }

    return idx;
}

static void __pushdown(heap_t * h, unsigned int idx)
{
    while (1)
    {
        unsigned int childl, childr, child;

        childl = __child_left(idx);
        childr = __child_right(idx);

        if (childr >= h->count)
        {
            /* can't pushdown any further */
            if (childl >= h->count)
                return;

            child = childl;
        }
        /* find biggest child */
        else if (h->cmp(h->array[childl], h->array[childr], h->udata) < 0)
            child = childr;
        else
            child = childl;

        /* idx is smaller than child */
        if (h->cmp(h->array[idx], h->array[child], h->udata) < 0)
        {
            __swap(h, idx, child);
            idx = child;
            /* bigger than the biggest child, we stop, we win */
        }
        else
            return;
    }
}

static int __heap_offerx(heap_t * h, void *item)
{
    h->array[h->count] = item;

    /* ensure heap properties */
    __pushup(h, h->count++);
    return 0;
}

int heap_offerx(heap_t * h, void *item)
{
    if (!item)
        return -1;
    if (h->count == h->size)
        return -1;
    return __heap_offerx(h, item);
}

int heap_offer(heap_t * h, void *item)
{
    if (!item)
        return -1;
    if (-1 == __ensurecapacity(h))
        return -1;
    return __heap_offerx(h, item);
}

void *heap_poll(heap_t * h)
{
    if (0 == heap_count(h))
        return NULL;

    void *item = h->array[0];

    h->array[0] = NULL;
    __swap(h, 0, h->count - 1);
    h->count--;

    if (h->count > 0)
        __pushdown(h, 0);

    return item;
}

void *heap_peek(heap_t * h)
{
    if (0 == heap_count(h))
        return NULL;

    return h->array[0];
}

void heap_clear(heap_t * h)
{
    h->count = 0;
}

/**
 * @return item's index on the heap's array; otherwise -1 */
static int __item_get_idx(heap_t * h, const void *item)
{
    unsigned int idx;

    for (idx = 0; idx < h->count; idx++){
        if(h->array[idx]==item){
            return idx;
        }
    }
    //if (0 == h->cmp(h->array[idx], item, h->udata))
    //     return idx;
    return -1;
}

void *heap_remove_item(heap_t * h, const void *item)
{
    int idx = __item_get_idx(h, item);

    if (idx == -1)
        return NULL;

    /* swap the item we found with the last item on the heap */
    void *ret_item = h->array[idx];
    h->array[idx] = h->array[h->count - 1];
    h->array[h->count - 1] = NULL;

    h->count -= 1;

    /* ensure heap property */
    __pushup(h, idx);

    return ret_item;
}

int heap_contains_item(heap_t * h, const void *item)
{
    return __item_get_idx(h, item) != -1;
}

int heap_count(heap_t * h)
{
    return h->count;
}

int heap_size(heap_t * h)
{
    return h->size;
}

/*--------------------------------------------------------------79-characters-*/

测试,test.cc

#include <iostream>
#include "heap.h"
using namespace std;
static int counter=0;
class IntCount{
public:
    IntCount(){
        value_=counter++;
    }
    IntCount(int value){
        value_=value;
    }
    bool operator >(const IntCount &i){
        return value_>i.value_;
    }
    void Print(){
        std::cout<<"value "<<value_<<std::endl;
    }
private:
    int value_{0};
};
int heap_cmp(const void *a,const void *b,const void *udata){
    IntCount *l=(IntCount *)a;
    IntCount *r=(IntCount *)b;
    if(*l>*r){
        return -1;
    }else{
        return 1;
    }
}

int main()
{
    heap_t *heap=heap_new(heap_cmp,nullptr);
    IntCount *a=new IntCount();
    IntCount *b=new IntCount();
    IntCount *c=new IntCount();
    IntCount *d=new IntCount();
    IntCount *e=new IntCount(2);
    heap_offerx(heap,(void*)c);
    heap_offerx(heap,(void*)b);
    heap_offerx(heap,(void*)d);
    heap_offerx(heap,(void*)a);
    heap_offerx(heap,(void*)e);
    heap_remove_item(heap,b);
    int eles=heap_count(heap);
    IntCount *temp=nullptr;
    for(int i=0;i<eles;i++){
    temp=(IntCount*)heap_poll(heap);
    temp->Print();
    }
    return 0;
}

[1] https://github.com/willemt/yabtorrent

相关文章

网友评论

      本文标题:c语言最大最小堆(heap)

      本文链接:https://www.haomeiwen.com/subject/zradqctx.html