Skip to content

Commit 1fca666

Browse files
committed
init
0 parents  commit 1fca666

File tree

7 files changed

+647
-0
lines changed

7 files changed

+647
-0
lines changed

Makefile

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
CFLAGS += -O0 -g -Wall
2+
all: test test2
3+
4+
test: test.o heap.h heap.o
5+
$(CC) $(CFLAGS) test.o heap.o -o test
6+
7+
test2: test2.o fibheap.h fibheap.o
8+
$(CC) $(CFLAGS) test2.o fibheap.o -o test2
9+
10+
clean:
11+
rm -rf *.o test2 test

fibheap.c

Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
/**
2+
* author: Liu Zhiyong<[email protected]>
3+
*/
4+
5+
#include <limits.h>
6+
#include <stdlib.h>
7+
#include <string.h>
8+
#include <stdio.h>
9+
#include <assert.h>
10+
#include "fibheap.h"
11+
12+
static fibnode_t *fibnode_remove(fibnode_t *node)
13+
{
14+
fibnode_t *ret = (node != node->left) ? node->left : NULL;
15+
16+
node->right->left = node->left;
17+
node->left->right = node->right;
18+
node->left = node;
19+
node->right = node;
20+
21+
return ret;
22+
}
23+
24+
static void fibnode_insert(fibnode_t *a, fibnode_t *b)
25+
{
26+
b->left = a;
27+
b->right = a->right;
28+
29+
a->right->left = b;
30+
a->right = b;
31+
}
32+
33+
static void fibnode_union(fibnode_t *a, fibnode_t *b)
34+
{
35+
fibnode_t *atail = a->right;
36+
fibnode_t *btail = b->right;
37+
38+
atail->left = b;
39+
b->right = atail;
40+
41+
a->right = btail;
42+
btail->left = a;
43+
}
44+
45+
static void fibheap_link(fibnode_t *node, fibnode_t *parent)
46+
{
47+
if (parent->child == NULL)
48+
parent->child = node;
49+
else
50+
fibnode_insert(parent->child, node);
51+
node->parent = parent;
52+
node->mark = 0;
53+
parent->degree++;
54+
}
55+
56+
static void fibheap_cut(fibheap_t *fib, fibnode_t *node, fibnode_t *parent)
57+
{
58+
parent->degree--;
59+
parent->child = fibnode_remove(node);
60+
61+
node->parent = NULL;
62+
node->mark = 0;
63+
64+
fibnode_insert(fib->min, node);
65+
}
66+
67+
static void __fibheap_insert(fibheap_t *fib, fibnode_t *node)
68+
{
69+
if (fib->min == NULL) {
70+
fib->min = node;
71+
} else {
72+
fibnode_insert(fib->min, node);
73+
if (node->key < fib->min->key)
74+
fib->min = node;
75+
}
76+
}
77+
78+
static void fibheap_consolidate(fibheap_t *fib)
79+
{
80+
int i, max = 0;
81+
fibnode_t *tmp, *node, *min, *stack[1 + 8 * sizeof(long)] = {NULL};
82+
83+
while ((min = fib->min) != NULL) {
84+
fib->min = fibnode_remove(min);
85+
for (i = min->degree; stack[i] != NULL; i++) {
86+
node = stack[i], stack[i] = NULL;
87+
if (min->key > node->key)
88+
tmp = min, min = node, node = tmp;
89+
90+
fibheap_link(node, min);
91+
}
92+
stack[i] = min;
93+
if (i > max)
94+
max = i;
95+
}
96+
97+
assert(max < 1 + 8 * sizeof(long));
98+
for (i = 0; i <= max; i++) {
99+
if (stack[i])
100+
__fibheap_insert(fib, stack[i]);
101+
}
102+
}
103+
104+
static void fibheap_cascading_cut(fibheap_t *fib, fibnode_t *node)
105+
{
106+
fibnode_t *parent;
107+
while ((parent = node->parent) != NULL) {
108+
if (node->mark == 0) {
109+
node->mark = 1;
110+
return;
111+
}
112+
fibheap_cut(fib, node, parent);
113+
node = parent;
114+
}
115+
}
116+
117+
static fibnode_t *__fibheap_extract_min(fibheap_t *fib)
118+
{
119+
fibnode_t *n, *min = fib->min;
120+
121+
// 将min的子节点合并到堆的根节点上
122+
if (min->child) {
123+
min->child->parent = NULL;
124+
for (n = min->child->left; n != min->child; n = n->left)
125+
n->parent = NULL;
126+
fibnode_union(min, min->child);
127+
}
128+
129+
fib->nodes--;
130+
fib->min = fibnode_remove(min);
131+
fibheap_consolidate(fib);
132+
133+
FIBNODE_INIT(min);
134+
return min;
135+
}
136+
137+
void fibheap_init(fibheap_t *fib)
138+
{
139+
*fib = FIBHEAP_INIT();
140+
}
141+
142+
void fibheap_fini(fibheap_t *fib)
143+
{
144+
while (fib->min) {
145+
fibnode_t *min = __fibheap_extract_min(fib);
146+
FIBNODE_INIT(min);
147+
}
148+
*fib = FIBHEAP_INIT();
149+
}
150+
151+
int fibheap_insert(fibheap_t *fib, fibnode_t *node)
152+
{
153+
assert(node->key > FIBHEAP_MINKEY);
154+
155+
FIBNODE_INIT(node);
156+
__fibheap_insert(fib, node);
157+
fib->nodes++;
158+
159+
return 0;
160+
}
161+
162+
fibnode_t *fibheap_min(fibheap_t *fib)
163+
{
164+
return fib->min ? fib->min : NULL;
165+
}
166+
167+
fibnode_t *fibheap_extract_min(fibheap_t *fib)
168+
{
169+
return fib->min ? __fibheap_extract_min(fib) : NULL;
170+
}
171+
172+
int fibheap_union(fibheap_t *fib, fibheap_t *other)
173+
{
174+
if (!fib->min || !other->min) {
175+
if (!fib->min)
176+
*fib = *other;
177+
goto DONE;
178+
}
179+
180+
// 链接两个堆的根的双向链表
181+
fibnode_union(fib->min, other->min);
182+
// 比较最小的节点
183+
if (fib->min->key > other->min->key)
184+
fib->min = other->min;
185+
fib->nodes += other->nodes;
186+
DONE:
187+
*other = FIBHEAP_INIT();
188+
return 0;
189+
}
190+
191+
static int __fibheap_decrease_key(fibheap_t *fib, fibnode_t *node, long key)
192+
{
193+
fibnode_t *parent = node->parent;
194+
node->key = key;
195+
196+
if (parent && node->key <= parent->key) {
197+
fibheap_cut(fib, node, parent);
198+
fibheap_cascading_cut(fib, parent);
199+
}
200+
201+
if (node->key <= fib->min->key)
202+
fib->min = node;
203+
204+
return 0;
205+
}
206+
207+
int fibheap_decrease_key(fibheap_t *fib, fibnode_t *node, long key)
208+
{
209+
assert(key > FIBHEAP_MINKEY && node->key > key);
210+
return node->key != key ? __fibheap_decrease_key(fib, node, key) : 0;
211+
}
212+
213+
int fibheap_delete(fibheap_t *fib, fibnode_t *node)
214+
{
215+
long okey = node->key;
216+
217+
__fibheap_decrease_key(fib, node, FIBHEAP_MINKEY);
218+
assert(node == fib->min);
219+
__fibheap_extract_min(fib);
220+
221+
node->key = okey;
222+
223+
return 0;
224+
}

fibheap.h

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/**
2+
* author: Liu Zhiyong<[email protected]>
3+
*
4+
* fibheap_union O(1)
5+
* fibheap_insert O(1)
6+
* fibheap_min O(1)
7+
* fibheap_delete O(lgn) amortized, O(n) worst case
8+
* fibheap_extract_min O(lgn) amortized, O(n) worst case
9+
* fibheap_decrease_key O(1) amortized, O(lgn) worst case
10+
*/
11+
12+
#ifndef __FIBHEAP_H__
13+
#define __FIBHEAP_H__
14+
15+
#define FIBHEAP_MINKEY LONG_MIN
16+
17+
#define FIBHEAP_INIT() (fibheap_t){0, NULL}
18+
#define FIBNODE_INIT(_n) do { fibnode_t *n = _n; n->parent=n->child=NULL;n->left=n->right=n;} while (0)
19+
20+
typedef struct fibnode {
21+
long key;
22+
char mark; // 标记节点成为另一个节点的子节点后失去过子节点
23+
unsigned short degree; // 子节点数目
24+
struct fibnode *parent; // 父指针
25+
struct fibnode *child; // 字节点
26+
struct fibnode *left; // 左兄节点
27+
struct fibnode *right; // 右兄节点, 这两个指针窜成一个双向链表, 没有大小次序
28+
} fibnode_t;
29+
30+
typedef struct fibheap {
31+
size_t nodes; // 包含的关键字数目
32+
struct fibnode *min; // 指向fibheap中最小关键字的根节点
33+
} fibheap_t;
34+
35+
void fibheap_init(fibheap_t *fib);
36+
void fibheap_fini(fibheap_t *fib);
37+
38+
int fibheap_union(fibheap_t *fib, fibheap_t *other);
39+
40+
int fibheap_insert(fibheap_t *fib, fibnode_t *node);
41+
int fibheap_delete(fibheap_t *fib, fibnode_t *node);
42+
int fibheap_decrease_key(fibheap_t *fib, fibnode_t *node, long key);
43+
fibnode_t *fibheap_extract_min(fibheap_t *fib);
44+
fibnode_t *fibheap_min(fibheap_t *fib);
45+
46+
#endif /* _FIBHEAP_H_ */

0 commit comments

Comments
 (0)