开源 C 语言库 Melon:斐波那契堆 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
monkeyNik
V2EX    C

开源 C 语言库 Melon:斐波那契堆

  •  
  •   monkeyNik 2023-01-20 18:16:23 +08:00 1951 次点击
    这是一个创建于 1061 天前的主题,其中的信息可能已经有所发展或是发生改变。

    本篇介绍开源 C 语言库 Melon 的斐波那契堆的使用。关于 Melon 库,这是一个开源的 C 语言库,它具有:开箱即用、无第三方依赖、安装部署简单、中英文文档齐全等优势。

    Github repo

    简介

    关于斐波那契堆,感兴趣的朋友可以参考《算法导论或者是各类讲解博客。

    本篇介绍的是斐波那契最小堆,但对于判断条件和初始化属性进行调整后,也可实现最大堆。

    数据结构各类操作时间复杂度:

    • 创建堆:O(1)
    • 插入:O(1)
    • 取最小值:O(1)
    • 将最小值从堆中移除:O(logN)
    • 合并堆:O(1)
    • 将堆结点 key 值减小:O(1)
    • 移除某个堆结点:O(logN)

    由此,我们可以看到斐波那契堆非常适合频繁插入和删除以及取得极值(最小值)结点操作。这样的操作第一个能想到的场景就是实现对超时定时器的管理。

    使用

    我们先给出示例代码:

    #include <stdio.h> #include <stdlib.h> #include "mln_core.h" #include "mln_log.h" #include "mln_fheap.h" static int cmp_handler(const void *key1, const void *key2) { return *(int *)key1 < *(int *)key2? 0: 1; } static void copy_handler(void *old_key, void *new_key) { *(int *)old_key = *(int *)new_key; } int main(int argc, char *argv[]) { int i = 10, min = 0; mln_fheap_t *fh; mln_fheap_node_t *fn; struct mln_fheap_attr fattr; struct mln_core_attr cattr; cattr.argc = argc; cattr.argv = argv; cattr.global_init = NULL; cattr.master_process = NULL; cattr.worker_process = NULL; if (mln_core_init(&cattr) < 0) { fprintf(stderr, "init failed\n"); return -1; } fattr.pool = NULL; fattr.pool_alloc = NULL; fattr.pool_free = NULL; fattr.cmp = cmp_handler; fattr.copy = copy_handler; fattr.key_free = NULL; fattr.min_val = &min; fattr.min_val_size = sizeof(min); fh = mln_fheap_new(&fattr); if (fh == NULL) { mln_log(error, "fheap init failed.\n"); return -1; } fn = mln_fheap_node_new(fh, &i); if (fn == NULL) { mln_log(error, "fheap node init failed.\n"); return -1; } mln_fheap_insert(fh, fn); fn = mln_fheap_minimum(fh); mln_log(debug, "%d\n", *((int *)mln_fheap_node_key(fn))); mln_fheap_free(fh); return 0; } 

    main函数中的流程大致如下:

    1. 对 Melon 库进行初始化
    2. 设置斐波那契堆初始化属性
    3. 对斐波那契堆进行初始化
    4. 创建斐波那契堆结点
    5. 将新建的斐波那契堆结点插入堆中
    6. 取斐波那契堆中最小 key 值的堆结点
    7. 销毁斐波那契堆结构

    Melon 中,使用斐波那契堆需要引入mln_fheap.h头文件。

    这里要对堆初始化属性进行一番说明:

    struct mln_fheap_attr { void *pool; fheap_pool_alloc_handler pool_alloc; fheap_pool_free_handler pool_free; fheap_cmp cmp; fheap_copy copy; fheap_key_free key_free; void *min_val; mln_size_t min_val_size; }; 

    其中:

    • pool是用于支持用户自定义内存池之用的,该指针将于pool_allocpool_free配合使用。
    • pool_alloc是用于支持用户自定义分配内存之用,该函数指针第一个参数为pool,第二个参数是要分配的内存大小。
    • pool_free是用于支持用户自定义释放内存之用,该函数指针第一个参数为要释放的内存起始地址。
    • cmp是用于对两个堆结点所关联的用户自定义数据进行比较大小之用的。
    • copy是用于*将堆结点 key 值减小(decrease_key)*时,将新 key 值(即用户自定义结构)拷贝到老 key 值中。
    • key_free是用于对堆结点所关联的用户自定义数据进行释放之用的。
    • min_val用户自定义结构的最小值,因为这里实现的是最小堆,因此需要给出一个相对所有插入本堆的结点而言都小的最小值范例。
    • min_val_size用户自定义最小值结构所占字节数,即min_val指向的结构的字节大小。

    这些属性字段中,除cmpcopymin_valmin_val_size外,其余若无需求,则可以置NULL

    内存池和分配释放函数主要是用于堆结点的分配和释放之用。之所以不直接给出一个 Melon 实现的内存池结构指针,是因为不希望斐波那契堆代码与内存池类型强关联,这样允许斐波那契堆可以接入使用者自己定义的内存管理功能。

    关于斐波那契堆代码的演进,与此前红黑树文章基本类似,再次就不过多阐述了。

    斐波那契堆在整个 Melon 框架中的使用场景基本都是在超时定时器的维护上面。

    结语

    在 Melon 中,斐波那契堆的使用相较于红黑树而言确实少了很多,因此其演进的速度相对来说会慢一些,演化方向也会受到类似红黑树结构演进的影响。

    同时,因为使用并不是很广泛,因此此前也有用户发起了 issue ,提出了堆结构存在实现错误,并给出了问题点。当然,问题早已被修复和验证。

    在此非常感谢各位使用者的使用和反馈,你们的反馈也是 Melon 库前进的动力。

    欢迎各位对 Melon 感兴趣的读者访问其Github 仓库

    感谢阅读!

    adian
        1
    adian  
       2023-01-20 20:35:53 +08:00
    酷!
    cortexm3
        2
    cortexm3  
       2023-01-20 22:11:07 +08:00
    cool +1
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1066 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 24ms UTC 18:16 PVG 02:16 LAX 10:16 JFK 13:16
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86