libevent中min_heap分析

本文深入探讨了最小堆的数据结构及其关键操作实现,包括构造、销毁、初始化元素、判断堆是否为空、获取堆大小、获取顶部元素、堆元素保留、压入元素、弹出元素、调整元素位置、擦除指定元素、向上调整和向下调整元素等。通过清晰的代码示例,展示了如何在最小堆中高效地进行各种操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

typedef struct min_heap
{
    struct event** p;
    unsigned n, a;
} min_heap_t;

static inline void         min_heap_ctor_(min_heap_t* s);
static inline void         min_heap_dtor_(min_heap_t* s);
static inline void         min_heap_elem_init_(struct event* e);
static inline int         min_heap_elt_is_top_(const struct event *e);
static inline int         min_heap_empty_(min_heap_t* s);
static inline unsigned         min_heap_size_(min_heap_t* s);
static inline struct event*  min_heap_top_(min_heap_t* s);
static inline int         min_heap_reserve_(min_heap_t* s, unsigned n);
static inline int         min_heap_push_(min_heap_t* s, struct event* e);
static inline struct event*  min_heap_pop_(min_heap_t* s);
static inline int         min_heap_adjust_(min_heap_t *s, struct event* e);
static inline int         min_heap_erase_(min_heap_t* s, struct event* e);
static inline void         min_heap_shift_up_(min_heap_t* s, unsigned hole_index, struct event* e);
static inline void         min_heap_shift_up_unconditional_(min_heap_t* s, unsigned hole_index, struct event* e);
static inline void         min_heap_shift_down_(min_heap_t* s, unsigned hole_index, struct event* e);

#define min_heap_elem_greater(a, b) \
    (evutil_timercmp(&(a)->ev_timeout, &(b)->ev_timeout, >))

void min_heap_ctor_(min_heap_t* s) { s->p = 0; s->n = 0; s->a = 0; }
void min_heap_dtor_(min_heap_t* s) { if (s->p) mm_free(s->p); }
void min_heap_elem_init_(struct event* e) { e->ev_timeout_pos.min_heap_idx = -1; }
int min_heap_empty_(min_heap_t* s) { return 0u == s->n; }
unsigned min_heap_size_(min_heap_t* s) { return s->n; }
struct event* min_heap_top_(min_heap_t* s) { return s->n ? *s->p : 0; }

int min_heap_push_(min_heap_t* s, struct event* e)
{
    if (min_heap_reserve_(s, s->n + 1))
        return -1;
    min_heap_shift_up_(s, s->n++, e);
    return 0;
}

struct event* min_heap_pop_(min_heap_t* s)
{
    if (s->n)
    {
        struct event* e = *s->p;
        min_heap_shift_down_(s, 0u, s->p[--s->n]);
        e->ev_timeout_pos.min_heap_idx = -1;
        return e;
    }
    return 0;
}

int min_heap_elt_is_top_(const struct event *e)
{
    return e->ev_timeout_pos.min_heap_idx == 0;
}

int min_heap_erase_(min_heap_t* s, struct event* e)
{
    if (-1 != e->ev_timeout_pos.min_heap_idx)
    {
        struct event *last = s->p[--s->n];
        unsigned parent = (e->ev_timeout_pos.min_heap_idx - 1) / 2;
        /* we replace e with the last element in the heap.  We might need to
           shift it upward if it is less than its parent, or downward if it is
           greater than one or both its children. Since the children are known
           to be less than the parent, it can't need to shift both up and
           down. */
        if (e->ev_timeout_pos.min_heap_idx > 0 && min_heap_elem_greater(s->p[parent], last))
            min_heap_shift_up_unconditional_(s, e->ev_timeout_pos.min_heap_idx, last);
        else
            min_heap_shift_down_(s, e->ev_timeout_pos.min_heap_idx, last);
        e->ev_timeout_pos.min_heap_idx = -1;
        return 0;
    }
    return -1;
}

int min_heap_adjust_(min_heap_t *s, struct event *e)
{
    if (-1 == e->ev_timeout_pos.min_heap_idx) {
        return min_heap_push_(s, e);
    } else {
        unsigned parent = (e->ev_timeout_pos.min_heap_idx - 1) / 2;
        /* The position of e has changed; we shift it up or down
         * as needed.  We can't need to do both. */
        if (e->ev_timeout_pos.min_heap_idx > 0 && min_heap_elem_greater(s->p[parent], e))
            min_heap_shift_up_unconditional_(s, e->ev_timeout_pos.min_heap_idx, e);
        else
            min_heap_shift_down_(s, e->ev_timeout_pos.min_heap_idx, e);
        return 0;
    }
    return -1;
}

int min_heap_reserve_(min_heap_t* s, unsigned n)
{
    if (s->a < n)
    {
        struct event** p;
        unsigned a = s->a ? s->a * 2 : 8;
        if (a < n)
            a = n;
        if (!(p = (struct event**)mm_realloc(s->p, a * sizeof *p)))
            return -1;
        s->p = p;
        s->a = a;
    }
    return 0;
}
//主要算法思想是填补空洞,最好找到合适的位置再安插
void min_heap_shift_up_unconditional_(min_heap_t* s, unsigned hole_index, struct event* e)
{
    unsigned parent = (hole_index - 1) / 2;
    do
    {
//如果父节点>value[hole_index],父节点下沉 (s
->p[hole_index] = s->p[parent])->ev_timeout_pos.min_heap_idx = hole_index;
//hole_index替换为parent hole_index
= parent; parent = (hole_index - 1) / 2; } while (hole_index && min_heap_elem_greater(s->p[parent], e)); (s->p[hole_index] = e)->ev_timeout_pos.min_heap_idx = hole_index; } void min_heap_shift_up_(min_heap_t* s, unsigned hole_index, struct event* e) { unsigned parent = (hole_index - 1) / 2; while (hole_index && min_heap_elem_greater(s->p[parent], e)) { (s->p[hole_index] = s->p[parent])->ev_timeout_pos.min_heap_idx = hole_index; hole_index = parent; parent = (hole_index - 1) / 2; } (s->p[hole_index] = e)->ev_timeout_pos.min_heap_idx = hole_index; } void min_heap_shift_down_(min_heap_t* s, unsigned hole_index, struct event* e) { unsigned min_child = 2 * (hole_index + 1); while (min_child <= s->n) { min_child -= min_child == s->n || min_heap_elem_greater(s->p[min_child], s->p[min_child - 1]); if (!(min_heap_elem_greater(e, s->p[min_child]))) break; (s->p[hole_index] = s->p[min_child])->ev_timeout_pos.min_heap_idx = hole_index; hole_index = min_child; min_child = 2 * (hole_index + 1); } (s->p[hole_index] = e)->ev_timeout_pos.min_heap_idx = hole_index; }

暂时记录下,明天继续看,figthing!

实现的很清晰,不得不佩服作者清晰的思维呀。菜鸟学习ing!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值