libevent中的時間管理 小根堆

2021-08-04 13:22:41 字數 4578 閱讀 5726

型別名稱: 最小堆(minheap)

資料物件集: 完全二叉樹,每個結點的元素值不大於其子結點的元素值

最大堆同理可得

是不是堆要注意從根結點到任意結點路徑上結點序列的有序性!

另外 ,關於堆,為了保證陣列第乙個元素就是heap的根節點, heap基本上都是用陣列(或者其他的連續儲存空間)作為其儲存結構的。

2.1 堆的定義

//堆的定義

typedef

struct min_heap

min_heap_t;

關於p,由realloc分配,malloc分配的記憶體是位於堆,realloc則對malloc申請的記憶體進行大小的調整

p陣列元素為event*,n表示目前儲存了多少個元素,a表示p指向的記憶體的尺寸。

其中結構體event定義了min_heap_idx

struct event
2.2 典型小根堆與libevent中的差別
heap[size++] 

//下面就是 shift_up()的**邏輯,不斷的將 new 向上調整

_child = size;

while(_child>0) // 迴圈

// 下面就是 shift_up()的**邏輯,不斷的將 new 的「預留位置」向上調整

_hole = size; // _hole 就是為 new 預留的位置,但並不立刻將 new 放上

while(_hole>0) // 迴圈

heap[_hole] = new; // 調整結束,將 new 插入到_hole 指示的位置

size++; // 元素個數+1

2.3 **例項 - 最小堆的操作 之插入

知道了libevent中與典型最小堆的不同外,以上面的插入為例補充libevent中最小堆的**操作

檢查調整記憶體空間大小 –> 呼叫shift_up_插入

static inline int            min_heap_push(min_heap_t* s, struct

event* e);

int min_heap_push(min_heap_t* s, struct

event* e)

libevent中的 min_heap_shift_up_

從上調整,其中,s->p[index]->min_heap_idx 為event結構體的min_heap_idx

void min_heap_shift_up_(min_heap_t* s, unsigned hole_index, struct event* e)

(s->p[hole_index] = e)->min_heap_idx = hole_index;

}

2.4 **例項 - 最小堆的操作 之取出

大部分時候,從堆裡取元素只侷限於取根節點。取完後,需要重新調整樹使其依然為乙個heap。

0;}

min_heap_shift_down_ 函式進行向下調整

/* hole_index 為取出的元素的位置,e為最右最下的元素值 */

void min_heap_shift_down_(min_heap_t* s, unsigned hole_index, struct event* e)

/* 執行第二步過程,將最右最下的節點插到空缺處 */

min_heap_shift_up_(s, hole_index, e);

}

//file : minheap-internal.h

#ifndef _min_heap_h_

#define _min_heap_h_

#include "event2/event.h"

#include "event2/event_struct.h"

#include "event2/util.h"

//堆的定義

typedef

struct min_heap

min_heap_t;

//static inline 內聯函式,c++中的巨集定義,提高函式呼叫效率

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_elem_greater(struct event *a, struct event *b);

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_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_down_(min_heap_t* s, unsigned hole_index, struct event* e); //向下調整

int min_heap_elem_greater(struct event *a, struct event *b)

void min_heap_ctor(min_heap_t* s) //建立

void min_heap_dtor(min_heap_t* s) //刪除

void min_heap_elem_init(struct event* e)

int min_heap_empty(min_heap_t* s)

unsigned min_heap_size(min_heap_t* s)

struct event* min_heap_top(min_heap_t* s)

int min_heap_push(min_heap_t* s, struct event* e)

struct event* min_heap_pop(min_heap_t* s)

return0;}

int min_heap_erase(min_heap_t* s, struct event* e)

return -1;

}int min_heap_reserve(min_heap_t* s, unsigned n)

return0;}

void min_heap_shift_up_(min_heap_t* s, unsigned hole_index, struct event* e)

(s->p[hole_index] = e)->min_heap_idx = hole_index;

}void min_heap_shift_down_(min_heap_t* s, unsigned hole_index, struct event* e)

min_heap_shift_up_(s, hole_index, e);

}#endif /* _min_heap_h_ */

參考文章:

libevent中的時間管理 時間快取與校正

上一文章中,知道在libevent中,用了小根堆對timer事件進行管理,其key值對應事件 的超時時間,從小根堆中可以取出最小的超時時間 對於timer,libevnet有乙個時間管理機制,即下面要說到的等待時間管理,時間快取校正等 static int timeout next struct e...

時間管理的小技巧

這裡分享一下我現在用的時間管理小技巧。看過一些書,覺得很多都是講理論性的東西,感覺說的都是因為我生也有涯,事情無限多,所以要將有限的生命集中在對自己最重要的事情上,隨之而來的就是 1 先做重要且緊急的 2 再做重要不緊急的 3 再做緊急不重要的 4 最後再做不緊急也不重要的。那麼現在問題來了,什麼事...

時間管理的小技巧(續)

接著前面時間管理小技巧裡的討論,說說拖沓的問題,就我個人來說,拖沓主要由兩個原因組成 1.這個事情實在是不情願做,比如跟客戶吵架 2.今天很累,沒心思幹活 對於第一點,最好就是授權出去,讓別人做,例如推給老闆,例如指派下屬解決。如果實在是逃不掉,就盡早做,所謂早死早超生。對於第二點,如果這個事情處理...