Fibonacci Heap
What is implemented in Melon is minimum heap.
Similar to the red-black tree component, the Fibonacci heap component has three usages:
- Basic Usage
- Inline Usage (not supported in
MSVC
) - Container Usage
Header File
#include "mln_fheap.h"
Module
fheap
Data Structures
The Fibonacci heap and its heap node structure are used internally by the component. Developers don't need to care about the composition of these two data structures. Just use the functions/macros provided in this chapter to operate the heap and nodes.
Basic Usage
Functions/Macros
mln_fheap_new
mln_fheap_t *mln_fheap_new(void *min_val, struct mln_fheap_attr *attr);
struct mln_fheap_attr {
void *pool;//memory pool
fheap_pool_alloc_handler pool_alloc;//Memory pool allocation memory function pointer
fheap_pool_free_handler pool_free;//Memory pool release memory function pointer
fheap_cmp cmp;//comparison function
fheap_copy copy;//copy function
fheap_key_free key_free;//key release function
};
typedef int (*fheap_cmp)(const void *, const void *);
typedef void (*fheap_copy)(void *, void *);
typedef void (*fheap_key_free)(void *);
typedef void *(*fheap_pool_alloc_handler)(void *, mln_size_t);
typedef void (*fheap_pool_free_handler)(void *);
Description: Create a Fibonacci heap.
min_val
refers to the minimum value of the user-defined data type in the heap node, and the type of this pointer is consistent with the type of user-defined data in the heap node. Note that the memory pointed to by this pointer should not be changed, and its life cycle should at least run through the life cycle of the Fibonacci heap.attr
is the initialization attribute structure of the Fibonacci heap, which contains:pool
is a user-defined memory pool structure. If this item is notNULL
, the Fibonacci heap structure will be allocated from this memory pool, otherwise it will be allocated from the malloc library.pool_alloc
is the allocation memory function pointer of the memory pool, and this callback will be used whenpool
is not empty.pool_free
is the pointer to the free memory function of the memory pool, and this callback will be used whenpool
is not empty.cmp
is a function used to compare key. This function has two parameters, both of which are user-defined key structure pointers. Return0
if argument 1 is less than argument 2, otherwise returnnot 0
.copy
is used to copy the key structure, this callback function will be called whendecrease key
is used to change the original key value to a new key value. This function has two parameters, respectively: the original key value pointer and the new key value pointer.key_free
is the release function of the key value structure, if it does not need to be released, you can setNULL
.Here is an additional note, if you use the inline mode and do not use the
pool
field, you can directly set the attr parameter ofmln_fheap_new
toNULL
.
Return value: return mln_fheap_t
type pointer if successful, otherwise return NULL
mln_fheap_new_fast
mln_fheap_t *mln_fheap_new_fast(void *min_val, fheap_cmp cmp, fheap_copy copy, fheap_key_free key_free);
typedef int (*fheap_cmp)(const void *, const void *);
typedef void (*fheap_copy)(void *, void *);
typedef void (*fheap_key_free)(void *);
Description: Create a Fibonacci heap. The difference from mln_fheap_new_fast
is that memory pool is not supported and attributes are passed as function parameters.
min_val
refers to the minimum value of the user-defined data type in the heap node. The type of this pointer is consistent with the type of user-defined data in the heap node. Note that the memory pointed to by this pointer should not be changed, and its life cycle should last at least throughout the life cycle of the Fibonacci heap.cmp
is a function used for key comparison. This function has two parameters, both of which are user-defined key structure pointers. If parameter 1 is less than parameter 2, return0
, otherwise returnnon-0
.copy
is used to copy the key structure. This callback function will be called whendecrease key
is used to change the original key value to the new key value. This function has two parameters, which are: the original key value pointer and the new key value pointer.key_free
is the key value structure release function. If it does not need to be released, it can be set toNULL
.
Return value: Returns mln_fheap_t
type pointer if successful, otherwise returns NULL
mln_fheap_free
void mln_fheap_free(mln_fheap_t *fh);
Description: Destroy the Fibonacci heap, and release the key in the heap according to key_free
.
Return value: None
mln_fheap_node_new
mln_fheap_node_t *mln_fheap_node_new(mln_fheap_t *fh, void *key);
Description: Create a Fibonacci heap node structure, key
is the user-defined structure, fh
is the heap created by mln_fheap_new
.
Return value: return node structure pointer if successful, otherwise return NULL
mln_fheap_node_free
void mln_fheap_node_free(mln_fheap_t *fh, mln_fheap_node_t *fn);
Description: Release the resources of the node fn
of the Fibonacci heap fh
, and release the node data according to key_free
.
Return value: None
mln_fheap_insert
void mln_fheap_insert(mln_fheap_t *fh, mln_fheap_node_t *fn);
Description: Insert a heap node into the heap.
Return value: None
mln_fheap_minimum
mln_fheap_node_t *mln_fheap_minimum(mln_fheap_t *fh);
Description: Get the heap node with the smallest current key value in the heap fh
.
Return value: Returns the node structure successfully, otherwise returns NULL
mln_fheap_extract_min
mln_fheap_node_t *mln_fheap_extract_min(mln_fheap_t *fh);
Description: Take the node with the smallest key value in the heap fh
from the heap and return it.
Return value: return node structure if successful, otherwise return NULL
mln_fheap_decrease_key
int mln_fheap_decrease_key(mln_fheap_t *fh, mln_fheap_node_t *node, void *key);
Description: Downgrade the key value of the node node
in the heap fh
to the value given by key
.
Note: If key
is greater than the original key value, the execution will fail and return.
Return value: returns 0
on success, otherwise returns -1
mln_fheap_delete
void mln_fheap_delete(mln_fheap_t *fh, mln_fheap_node_t *node);
Description: Delete the node node
from the heap fh
, but it won't release node structure and associated user data.
Return value: None
Example
#include <stdio.h>
#include <stdlib.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;
fattr.pool = NULL;
fattr.pool_alloc = NULL;
fattr.pool_free = NULL;
fattr.cmp = cmp_handler;
fattr.copy = copy_handler;
fattr.key_free = NULL;
fh = mln_fheap_new(&min, &fattr);
if (fh == NULL) {
fprintf(stderr, "create fheap failed.\n");
return -1;
}
fn = mln_fheap_node_new(fh, &i);
if (fn == NULL) {
fprintf(stderr, "create fheap node failed.\n");
return -1;
}
mln_fheap_insert(fh, fn);
fn = mln_fheap_minimum(fh);
printf("%d\n", *((int *)mln_fheap_node_key(fn)));
mln_fheap_free(fh);
return 0;
}
Inline Usage
The purpose of inline usage is to improve the execution efficiency of each operation of the Fibonacci heap. The core difference between it and the basic usage is that the existence of callback functions (for example, cmp
, key_free
, copy
) is avoided. That is, the callback function is turned into an inline function, and the function call is eliminated by using compiler optimization.
Although this method of use is efficient, it also has some usage scenario limitations.
Scenario assumptions:
We first create a Fibonacci heap, which may be inserted into a lot of nodes in the future. And each node is a Fibonacci heap (we temporarily call it a sub-heap). The related operations of this sub-heap are independently maintained by its associated code files, and are not related to other sub-heaps.
Our requirement is: when the Fibonacci heap (non-sub-heap) executes
mln_fheap_free
, all sub-heaps will be released and destroyed together.
In the case of basic usage, we only need to set the key_free
attribute of the Fibonacci heap to mln_fheap_free
, and each sub-heap can be automatically released, regardless of the data type associated with each sub-heap node. What, and how to free these data types. Because these data types will be correctly released by the callback function set by the key_free
attribute of the sub-heap.
However, in inline usage, the comparison and release operations of node data need to be clearly specified which function is to be handled. Combined with our scenario assumptions above, it means that the Fibonacci heap must know the data type of each sub-heap, and then explicitly call the release function corresponding to the specified type to release resources. However, when resources are continuously nested between multiple data structures and code modules as in the above scenario, it is difficult for us to know the data types of other modules in a certain code module, and it is impossible to release these data type resources correctly. This is the scenario where inline usage doesn't quite work out.
The inline usage additionally provides a set of macro statement expressions to replace some functions in the basic usage:
- mln_fheap_inline_insert
- mln_fheap_inline_extract_min
- mln_fheap_inline_decrease_key
- mln_fheap_inline_delete
- mln_fheap_inline_node_free
- mln_fheap_inline_free
Functions/Macros
mln_fheap_inline_insert
mln_fheap_inline_insert(fh, fn, compare)
Description: Same as the function of mln_fheap_insert
, insert the node fn
into the Fibonacci heap fh
. compare
is the cmp
function in struct mln_fheap_attr
in the basic usage, but at this time the function can be declared as inline
, and it will be inlined after compiler optimization is turned on. If compare
is NULL
, it will try to get the cmp
callback function of the Fibonacci heap fh
.
Return value: same as mln_fheap_insert
mln_fheap_inline_extract_min
mln_fheap_inline_extract_min(fh, compare)
Description: Same as the function of mln_fheap_extract_min
, the heap node with the smallest value is removed from the heap and returned. compare
is the cmp
function in struct mln_fheap_attr
in the basic usage, but at this time the function can be declared as inline
, and it will be inlined after compiler optimization is turned on. If compare
is NULL
, it will try to get the cmp
callback function of the Fibonacci heap fh
.
Return value: same as mln_fheap_extract_min
mln_fheap_inline_decrease_key
mln_fheap_inline_decrease_key(fh, node, k, cpy, compare)
Description: Same as the function of mln_fheap_decrease_key
, reduce the key value of the node node
to k
. compare
is the cmp
function in struct mln_fheap_attr
in the basic usage, cpy
is the copy
function in struct mln_fheap_attr
, but at this time these two functions can be declared as inline
, and in Inlined after compiler optimization is turned on. If compare
is NULL
, it will try to get the cmp
callback function of the Fibonacci heap fh
. If cpy
is NULL
, it will try to get the copy
callback function of the Fibonacci heap fh
.
Return value: same as mln_fheap_decrease_key
mln_fheap_inline_delete
mln_fheap_inline_delete(fh, node, cpy, compare)
Description: Same as the function of mln_fheap_delete
, remove the node node
from the heap fh
. compare
is the cmp
function in struct mln_fheap_attr
in the basic usage, cpy
is the copy
function in struct mln_fheap_attr
, but at this time these two functions can be declared as inline
, and in Inlined after compiler optimization is turned on. If compare
is NULL
, it will try to get the cmp
callback function of the Fibonacci heap fh
. If cpy
is NULL
, it will try to get the copy
callback function of the Fibonacci heap fh
.
Return value: same as mln_fheap_delete
mln_fheap_inline_node_free
mln_fheap_inline_node_free(fh, fn, freer)
Description: Same as the function of mln_fheap_node_free
, release the node fn
. freer
is the key_free
function in struct mln_fheap_attr
in the basic usage, but this function can be declared as inline
at this time, and it will be inlined after compiler optimization is turned on. If freer
is NULL
, it will try to get the key_free
callback function of the Fibonacci heap fh
.
Return value: same as mln_fheap_node_free
mln_fheap_inline_free
mln_fheap_inline_free(fh, compare, freer)
Description: Same as the function of mln_fheap_free
, release the node fn
. freer
is the key_free
function in struct mln_fheap_attr
in the basic usage, but this function can be declared as inline
at this time, and it will be inlined after compiler optimization is turned on. If freer
is NULL
, it will try to get the key_free
callback function of the Fibonacci heap fh
.
Return value: same as mln_fheap_free
Example
#include <stdio.h>
#include <stdlib.h>
#include "mln_fheap.h"
static inline int cmp_handler(const void *key1, const void *key2) //inline
{
return *(int *)key1 < *(int *)key2? 0: 1;
}
static inline void copy_handler(void *old_key, void *new_key) //inline
{
*(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;
fh = mln_fheap_new(&min, NULL);
if (fh == NULL) {
fprintf(stderr, "fheap init failed.\n");
return -1;
}
fn = mln_fheap_node_new(fh, &i);
if (fn == NULL) {
fprintf(stderr, "fheap node init failed.\n");
return -1;
}
mln_fheap_inline_insert(fh, fn, cmp_handler); //inline insert
fn = mln_fheap_minimum(fh);
printf("%d\n", *((int *)mln_fheap_node_key(fn)));
mln_fheap_inline_free(fh, cmp_handler, NULL); //inline free
return 0;
}
Container Usage
The container usage does not conflict with the above two usages, on the contrary the container usage needs to use the functions/macros of the above two usages to operate the Fibonacci heap. The meaning of the container is to use the Fibonacci heap node structure as an attribute in the user-defined data structure. For example:
struct user_defined_s {
int int_val;
...
mln_fheap_node_t node; //Note that this is not a pointer
...
};
In this structure definition, node
is a Fibonacci heap node type, which is a member variable in the structure user_defined_s
.
Functions/Macros
In container usage, we use mln_fheap_node_init
to replace mln_fheap_node_new
to initialize the heap node. The difference between these two interfaces is that mln_fheap_node_init
does not dynamically create the node structure (because it has been defined in other custom structures and is created together when the custom structure is instantiated).
mln_fheap_node_init
mln_fheap_node_init(fn, k)
Description: Initialize the heap node pointer fn
, and associate the user-defined key k
with the node structure fn
.
Return value: heap node structure pointer fn
Example
#include <stdio.h>
#include <stdlib.h>
#include "mln_fheap.h"
typedef struct user_defined_s {
int val;
mln_fheap_node_t node; //自定义数据结构的成员
} ud_t;
static inline int cmp_handler(const void *key1, const void *key2)
{
return ((ud_t *)key1)->val < ((ud_t *)key2)->val? 0: 1;
}
static inline void copy_handler(void *old_key, void *new_key)
{
((ud_t *)old_key)->val = ((ud_t *)new_key)->val;
}
int main(int argc, char *argv[])
{
mln_fheap_t *fh;
ud_t min = {0, };
ud_t data1 = {1, };
ud_t data2 = {2, };
mln_fheap_node_t *fn;
fh = mln_fheap_new(&min, NULL);
if (fh == NULL) {
fprintf(stderr, "fheap init failed.\n");
return -1;
}
mln_fheap_node_init(&data1.node, &data1); //初始化堆结点
mln_fheap_node_init(&data2.node, &data2);
mln_fheap_inline_insert(fh, &data1.node, cmp_handler); //插入堆结点
mln_fheap_inline_insert(fh, &data2.node, cmp_handler);
fn = mln_fheap_minimum(fh);
//两种方式获取自定义数据
printf("%d\n", ((ud_t *)mln_fheap_node_key(fn))->val);
printf("%d\n", mln_container_of(fn, ud_t, node)->val);
mln_fheap_inline_free(fh, cmp_handler, NULL);
return 0;
}