-
Notifications
You must be signed in to change notification settings - Fork 0
/
Fibonacci.c
349 lines (317 loc) · 7.92 KB
/
Fibonacci.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include <limits.h>
// 定义斐波那契堆中的节点结构
typedef struct Node
{
int key; // 节点的键值
struct Node* parent, * child, * left, * right; // 指向父节点、子节点和兄弟节点的指针
unsigned degree : 7; // 节点的度数,使用7位足以存储最大度数
unsigned mark : 1; // 标记节点是否被切断过
} Node;
// 定义斐波那契堆结构
typedef struct
{
Node* min; // 指向最小节点的指针
int size; // 堆中节点的数量
} FibonacciHeap;
void consolidate(FibonacciHeap* heap);
void _consolidate(FibonacciHeap* heap);
// debug
void printHeap(FibonacciHeap* heap)
{
if (heap->min == NULL)
{
printf("Heap is empty\n");
return;
}
printf("Heap nodes: ");
Node* x = heap->min;
do
{
printf("%d ", x->key);
x = x->right;
} while (x != heap->min);
printf("\n");
}
// 创建一个新节点
Node* createNode(int key)
{
Node* node = (Node*)malloc(sizeof(Node));
node->key = key;
node->parent = node->child = NULL;
node->left = node->right = node; // 初始化为一个循环链表
node->degree = 0;
node->mark = 0;
return node;
}
// 创建一个空的斐波那契堆
FibonacciHeap* createHeap()
{
FibonacciHeap* heap = (FibonacciHeap*)malloc(sizeof(FibonacciHeap));
heap->min = NULL;
heap->size = 0;
return heap;
}
// 向斐波那契堆中插入一个新节点
void insert(FibonacciHeap* heap, int key)
{
// NoBugs
// printHeap(heap);
Node* node = createNode(key);
// 如果堆为空,新节点就是最小节点
if (heap->min == NULL)
{
heap->min = node;
}
else
{
// 将新节点插入到根节点列表中
node->right = heap->min->right;
node->left = heap->min;
heap->min->right->left = node;
heap->min->right = node;
// 更新最小节点
if (key < heap->min->key)
{
heap->min = node;
}
}
heap->size++;
}
// 合并两个斐波那契堆
void merge(FibonacciHeap* heap1, FibonacciHeap* heap2)
{
if (heap2->min == NULL)
return;
if (heap1->min == NULL)
{
*heap1 = *heap2;
free(heap2);
return;
}
// 合并两个堆的根节点列表
heap1->min->left->right = heap2->min->right;
heap2->min->right->left = heap1->min->left;
heap1->min->left = heap2->min;
heap2->min->right = heap1->min;
// 更新最小节点
if (heap2->min->key < heap1->min->key)
{
heap1->min = heap2->min;
}
free(heap2);
}
// 提取最小节点
Node* extractMin(FibonacciHeap* heap)
{
Node* z = heap->min;
if (z != NULL)
{
// 将最小节点的每个子节点添加到根链表中
if (z->child != NULL)
{
Node* child = z->child;
do
{
Node* next = child->right;
child->left = heap->min;
child->right = heap->min->right;
heap->min->right->left = child;
heap->min->right = child;
child = next;
} while (child != z->child);
}
// 移除最小节点
z->left->right = z->right;
z->right->left = z->left;
if (z == z->right)
{
heap->min = NULL;
}
else
{
heap->min = z->right;
// 调整堆
_consolidate(heap); // 需要实现合并堆
}
heap->size--;
}
return z;
}
void fibHeapLink(FibonacciHeap* heap, Node* y, Node* x)
{
// 将y链接为x的子节点
y->left->right = y->right;
y->right->left = y->left;
y->parent = x;
if (x->child == NULL)
{
x->child = y;
y->left = y->right = y;
}
else
{
y->left = x->child;
y->right = x->child->right;
x->child->right->left = y;
x->child->right = y;
}
x->degree++;
y->mark = 0;
}
// v2.0
// 合并堆的根链表,确保每个度数唯一
void _consolidate(FibonacciHeap* heap)
{
int D = (int)(log(heap->size) / log(2)) + 1;
// FibHeapNode *A[D];
// 动态分配 A 数组 Windows的Mingw不支持c99
Node** A = (Node**)malloc(D * sizeof(Node*));
// FibHeapNode *A = (FibHeapNode *) malloc(sizeof(FibHeapNode *[D]));
for (int i = 0; i < D; i++)
{
A[i] = NULL;
}
Node* x = heap->min;
int numRoots = 0;
if (x != NULL)
{
numRoots++;
x = x->right;
while (x != heap->min)
{
numRoots++;
x = x->right;
}
}
while (numRoots > 0)
{
int d = x->degree;
Node* next = x->right;
while (A[d] != NULL)
{
Node* y = A[d]; // y与x度数相同
if (x->key > y->key)
{ // 交换x与y
Node* temp = x;
x = y;
y = temp;
}
fibHeapLink(heap, y, x);
A[d] = NULL;
d++;
}
A[d] = x;
x = next;
numRoots--;
}
heap->min = NULL;
for (int i = 0; i < D; i++)
{
if (A[i] != NULL)
{
if (heap->min == NULL)
{
heap->min = A[i];
heap->min->left = heap->min;
heap->min->right = heap->min;
}
else
{
A[i]->left = heap->min;
A[i]->right = heap->min->right;
heap->min->right->left = A[i];
heap->min->right = A[i];
if (A[i]->key < heap->min->key)
{
heap->min = A[i];
}
}
}
}
// a small bug i forgot
free(A);
}
// 维护堆结构的辅助函数
void consolidate(FibonacciHeap* heap)
{
Node* A[50] = { NULL }, * x, * y, * w;
int i, l;
// 使用do-while循环替代原来的for循环,避免无限循环问题
Node* start = heap->min;
x = start;
do
{
l = x->degree;
while (A[l] != NULL)
{
y = A[l];
// 这里怎么有个空指针访问
if (x->key > y->key)
{
Node* temp = x;
x = y;
y = temp;
}
// 合并两个子堆
w = x->child;
y->parent = x;
x->child = y;
x->degree++;
if (w != NULL)
{
y->left->right = w->right;
w->right->left = y->left;
y->right = w;
w->left = y;
}
A[l] = NULL;
l++;
}
A[l] = x;
x = x->right;
} while (x != start); // 遍历所有根节点
heap->min = NULL;
// 重新构建根节点列表并找到最小节点
for (i = 0; i < 50; i++)
{
if (A[i] != NULL)
{
A[i]->left = A[i]->right = A[i]; // 重新建立循环链表结构
if (heap->min == NULL || A[i]->key < heap->min->key)
{
heap->min = A[i];
}
}
}
}
// 斐波那契堆排序
void fibonacciHeapSort(FibonacciHeap* heap)
{
Node* minNode;
while ((minNode = extractMin(heap)) != NULL)
{
printf("%d ", minNode->key);
free(minNode);
}
}
int main() {
FibonacciHeap* heap = createHeap();
srand(time(NULL)); // 设置随机种子
// 生成随机数据并插入斐波那契堆
for (int i = 0; i < 100000; i++) {
int key = rand() % 1000; // 生成0到999之间的随机数
insert(heap, key);
}
printf("Sorted keys:\n ");
fibonacciHeapSort(heap);
printf("\n ");
// 释放斐波那契堆占用的内存
while (extractMin(heap) != NULL)
;
free(heap);
return 0;
}