libevent源代码之最小堆的实现

libevent 中通过结构体min_heap_t实现最小堆,该结构体的声明如下:

typedef struct min_heap

{

struct event** p;

unsigned n, a;

} min_heap_t;

其中p是指向指针的指针,p指向了一个数组,该数组存储了event指针。N是申请数组的大小,a是当前数组中有几个元素。数组的大小在初始值设定为8,在添加元素时,数组内存不够时,重新申请一个2*n的数组,并把原数组中的内容拷贝到新申请的数组中。具体代码如下:

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;

}

和string的内存管理实现方式类似。

元素的入栈

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;

}

min_heap_reserve不再介绍,min_heap_shift_up中并不是简单的把e放在堆的尾部,然后进行最小堆的调整。min_heap_shift_up中认为数组的尾部是一个hole,如果parent大于e,则可直接赋值到尾部,减少了元素之间的赋值交换。直到找到e适合的hole,然后直接赋值。

代码如下:

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;

}

元素的出栈

和入栈类似,也是用一个hole来移动元素,避免元素的反复赋值交换

时间: 2024-10-12 20:44:40

libevent源代码之最小堆的实现的相关文章

Libevent源码分析(一):最小堆

Libevent中的timeout事件是使用最小堆来管理维护的.代码位于<minheap-internal.h>. 看函数命名和代码风格应该是一个C++程序员,函数名都挺好懂的,只是下面这个结构体变量命名比较坑.... typedef struct min_heap { struct event** p; unsigned n, a;//n队列元素的多少,a代表队列空间的大小. } min_heap_t; 注释是我加的,这命名,n啊a啊的,鬼知道啥意思....必须吐槽一下. 先来说说什么是最小

Jcompress: 一款基于huffman编码和最小堆的压缩、解压缩小程序

前言 最近基于huffman编码和最小堆排序算法实现了一个压缩.解压缩的小程序.其源代码已经上传到github上面: Jcompress下载地址 .在本人的github上面有一个叫Utility的repository,该分类下面有一个名为Jcompress的目录便是本文所述的压缩.解压缩小程序的源代码.后续会在Utility下面增加其他一些实用的小程序,比如基于socket的文件断点下载小程序等等.如果你读了此文觉得还不错,不防给笔者的github点个star, 哈哈.在正式介绍Jcompres

使用最小堆优化Dijkstra算法

OJ5.2很简单,使用priority_queue实现了最小堆竟然都过了OJ……每次遇到relax的问题时都简单粗暴地重新push进一个节点…… 然而正确的实现应该是下面这样的吧,关键在于swap堆中元素时使用pos数组存储改变位置后的编号为k的节点对应在堆中的位置.下面这种实现也很简单,d,v,p均存储在堆中,只有pos指明位置.源代码作者很聪明>_< #include <stdio.h> #define MAXN 1200 #define MAXM 1200000 #defin

POJ 3784 Running Median (最大最小堆)

最大最小堆动态求中位数 题意:输入M个数,当已输入的个数为奇数个时输出此时的中位数. 一共有M/2+1个中位数要输出,每一行10个. 分析: 用两个优先队列来模拟最大最小堆.中位数是x,就是有一半数比x小,一半数比x大. 刚好符合堆的特点. 用一个从大到小排序的优先队列q1来模拟小于x的数. 从小到大排序的优先队列q2来模拟大于x的数. 动态维护两个优先队列的元素个数.q1.size()=q2.size() 输入的数为偶数个时, q1.size()=q2.size()+1 输入的数为奇数个时.

通用的最小堆(最大堆)D-ary Heap

听说有一种最小(大)堆,不限于是完全二叉树,而是完全D叉树,名为D-ary Heap(http://en.wikipedia.org/wiki/D-ary_heap).D可以是1,2,3,4,100,对于优先队列该有的功能都没有问题. 动手写一个D-ary Heap,应该不难.简单起见,不考虑像STL一样通过template传入Comp类,下面的实现要求T类型重载了operator <和operator >. template<class T> class DaryHeap { s

最小堆的建立 插入 与删除

堆是完全二叉树,完全二叉树最大的特点就是 把数据储存在数组里 通过父子结点的关系来做  不用实际建树  parent=leftchild/2: leftchild=2*parent  右就加1这儿指的是序号关系,储存的时候注意是利用树的逻辑图 从上到下 从左到右编号12345..... 建堆:实际是把数据先放入数组(注意下标从1开始),对应逻辑图,写调整代码,我的基本思路是从数组末尾开始,对应元素与其父节点比较,满足条件就换值,并且对被换的调用调整函数(要单独写个调整函数)因为被换的一个是可能不

最小堆_最大堆

在大数查找中会遇到一类问题,例如在100亿条数据中找出 最大的(最小的) 前1000个元素.以int型4Byte为例,有1*1010*4 B = 4*1010/(230) B = 37.25G. 直接读取到内存中显然不合适,那么就需要: 首先,读取前1000个元素,建立一个最小堆(最大堆): 其次,之后每读取一个元素就与最小堆根元素(1000个数中最小值)进行比较: 如果,新元素大于(小于)堆顶元素 则,删除堆顶元素,将新元素插入堆顶.然后调整堆序,删除堆顶....循环往复 #define le

初学算法-基于最小堆的优先级队列C++实现

笔者近日实现了最小堆类及其派生的优先级队列,特将代码奉上,不足之处还请指出! 在实现优先级队列时,笔者表示萌萌哒没有用过template写派生类,结果写完了出现error: *** was not decleared in this scope..后来各种补上this->才完事,在CSDN(笔者的帖子地址? http://bbs.csdn.net/topics/391806995)上提问后才知道是模板参数依赖,笔者表示涨姿势了.. /**  * The Minimum Heap Class an

二叉堆 - 最小堆

二叉堆:一般我们拿来用的就是最大堆和最小堆. 最小堆:每个节点的值比它的左右子节点的值要大. 代码实现如下:参考Mark Allen Weiss<数据结构和算法分析>(第二版) 1 #include <cstdio> 2 #include <cstdlib> 3 4 #define MIN (1<<(sizeof(int)*8-1)) 5 6 typedef int Item; 7 typedef struct HeapStruct* heap; 8 9 s