c語言最大最小堆(heap)

?代碼是從[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

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市裆蒸,隨后出現(xiàn)的幾起案子熔萧,更是在濱河造成了極大的恐慌,老刑警劉巖僚祷,帶你破解...
    沈念sama閱讀 219,270評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件佛致,死亡現(xiàn)場離奇詭異,居然都是意外死亡辙谜,警方通過查閱死者的電腦和手機俺榆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來装哆,“玉大人罐脊,你說我怎么就攤上這事⊥汕伲” “怎么了萍桌?”我有些...
    開封第一講書人閱讀 165,630評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長凌简。 經常有香客問我梗夸,道長,這世上最難降的妖魔是什么号醉? 我笑而不...
    開封第一講書人閱讀 58,906評論 1 295
  • 正文 為了忘掉前任反症,我火速辦了婚禮,結果婚禮上畔派,老公的妹妹穿的比我還像新娘铅碍。我一直安慰自己,他們只是感情好线椰,可當我...
    茶點故事閱讀 67,928評論 6 392
  • 文/花漫 我一把揭開白布胞谈。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪烦绳。 梳的紋絲不亂的頭發(fā)上卿捎,一...
    開封第一講書人閱讀 51,718評論 1 305
  • 那天,我揣著相機與錄音径密,去河邊找鬼午阵。 笑死,一個胖子當著我的面吹牛享扔,可吹牛的內容都是我干的底桂。 我是一名探鬼主播,決...
    沈念sama閱讀 40,442評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼惧眠,長吁一口氣:“原來是場噩夢啊……” “哼籽懦!你這毒婦竟也來了?” 一聲冷哼從身側響起氛魁,我...
    開封第一講書人閱讀 39,345評論 0 276
  • 序言:老撾萬榮一對情侶失蹤暮顺,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后秀存,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體捶码,經...
    沈念sama閱讀 45,802評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,984評論 3 337
  • 正文 我和宋清朗相戀三年应又,在試婚紗的時候發(fā)現(xiàn)自己被綠了宙项。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,117評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡株扛,死狀恐怖尤筐,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情洞就,我是刑警寧澤盆繁,帶...
    沈念sama閱讀 35,810評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站旬蟋,受9級特大地震影響油昂,放射性物質發(fā)生泄漏。R本人自食惡果不足惜倾贰,卻給世界環(huán)境...
    茶點故事閱讀 41,462評論 3 331
  • 文/蒙蒙 一冕碟、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧匆浙,春花似錦安寺、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽言秸。三九已至,卻和暖如春迎捺,著一層夾襖步出監(jiān)牢的瞬間举畸,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評論 1 272
  • 我被黑心中介騙來泰國打工凳枝, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留抄沮,地道東北人。 一個月前我還...
    沈念sama閱讀 48,377評論 3 373
  • 正文 我出身青樓范舀,卻偏偏與公主長得像合是,于是被迫代替她去往敵國和親了罪。 傳聞我的和親對象是個殘疾皇子锭环,可洞房花燭夜當晚...
    茶點故事閱讀 45,060評論 2 355

推薦閱讀更多精彩內容

  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴謹 對...
    cosWriter閱讀 11,103評論 1 32
  • centos7安裝jdk,tomcat,nginx,redis,fastDFS的步驟* 1.linux****安裝...
    挑戰(zhàn)者666888閱讀 2,711評論 0 6
  • 2019年已過去兩個月,六分之一泊藕。再次看下年度夢想辅辩,完成六分之一了嗎? 這個月用向下娃圆,向下玫锋,停止,向上來形容吧……...
    諸葛大俠閱讀 154評論 0 2
  • 朋友這個詞讼呢,你會想到什么撩鹿?你想到的是那個好朋友,還是對自己很重要的朋友悦屏。又或者是那些早已忘記了节沦,不聯(lián)系的朋友。是普...
    秋燃講故事閱讀 193評論 0 0
  • 人生如浮云 短暫而漂泊不定 在我 卻有新的體會 浮云居無定所 還沒來得及看清身下的大地 懷著憧憬飄走了 還沒來得及...
    清水有情閱讀 509評論 0 0