/*FibonacciHeap.c -- 斐波那契堆實現檔案*/<br />#include "FibonacciHeap.h"</p><p>/*局部函式宣告*/</p><p>static Node * makeNode (const Item * const pi) ;<br />static int logBaseOnTwo (const int current) ;<br />static void link (Node * list, Node * const new_node) ;<br />static void cut (Node * const gap) ;<br />static void merge (Node * const root, Node * const child) ;<br />static void findCascadingCutAndRenew (Node * const pn, Node * const list) ;<br />static void renewDegree (Node * const parent, const int degree) ;<br />static void release (Node * const pn) ;</p><p>/*介面函數定義*/</p><p>BOOL Initialize_F (FibonacciHeap * const pfh)<br />{<br />*pfh = (struct fibonacciheap *) malloc (sizeof (struct fibonacciheap)) ;<br />if (NULL == *pfh)<br />return FALSE ;<br />(*pfh) -> min = NULL ;<br />(*pfh) -> current = 0 ;</p><p>return TRUE ;<br />}</p><p>BOOL IsEmpty_F (const FibonacciHeap * const pfh)<br />{<br />if (0 == (*pfh) -> current)<br />return TRUE ;<br />else<br />return FALSE ;<br />}</p><p>BOOL Insert_F (const FibonacciHeap * const pfh, const Item * const pi)<br />{<br />Node * new_node ;</p><p>new_node = makeNode (pi) ;<br />if (NULL == new_node)<br />return FALSE ;<br />if (IsEmpty_F (pfh))<br />(*pfh) -> min = new_node ;<br />else<br />{<br />link ((*pfh) -> min, new_node) ;<br />if (new_node -> item < (*pfh) -> min -> item)<br />(*pfh) -> min = new_node ;<br />}<br />(*pfh) -> current++ ;</p><p>return TRUE ;<br />}</p><p>Item DeleteMin_F (const FibonacciHeap * const pfh)<br />{<br />Node * * assistant, * temp ;<br />Node * scan, * record ;<br />Item return_value ;<br />int size, i ;</p><p>if (IsEmpty_F (pfh))<br />return EMPTY ;<br />/*Record the return value.*/<br />return_value = (*pfh) -> min -> item ;<br />/*If there is only one node in the heap.*/<br />if (1 == (*pfh) -> current)<br />{<br />free ((*pfh) -> min) ;<br />(*pfh) -> min = NULL ;<br />}<br />else<br />{<br />/*If it has one child at least.*/<br />if ((*pfh) -> min -> child != NULL)<br />{<br />scan = (*pfh) -> min -> child ;<br />do<br />{<br />(*pfh) -> min -> degree -= scan -> degree ;<br />temp = scan -> right ;<br />scan -> parent = NULL ;<br />link ((*pfh) -> min, scan) ;<br />scan = temp ;<br />}<br />while ((*pfh) -> min -> degree > 1)<br />;<br />/*Min -> child will be NULL for sure.*/<br />(*pfh) -> min -> child = NULL ;<br />}<br />/*If it has no child, only do these.*/<br />temp = (*pfh) -> min ;<br />/*Find a new min, it can be any point.*/<br />(*pfh) -> min = (*pfh) -> min -> right ;<br />/*Delete min.*/<br />cut (temp) ;<br />free (temp) ;<br />/*Find the real min.*/<br />/*It is O (N).*/<br />scan = record = (*pfh) -> min ;<br />do<br />{<br />if (scan -> right -> item < (*pfh) -> min -> item)<br />(*pfh) -> min = scan -> right ;<br />scan = scan -> right ;<br />}<br />while (scan != record)<br />;<br />/*Allocate memory space for the assistant list.*/<br />size = logBaseOnTwo ((*pfh) -> current - 1) ;<br />assistant = (Node * *) malloc (sizeof (Node *) * size) ;<br />if (NULL == assistant)<br />{<br />printf ("Faild in /"if (NULL == assistant)/"") ;<br />return EMPTY ;<br />}<br />for (i = 0; i < size; i++)<br />assistant[i] = NULL ;<br />/*Merge.*/<br />scan = record = (*pfh) -> min ;<br />for (i = 0; i < size; i++)<br />{<br />do<br />{<br />temp = scan -> right ;<br />/*As an example, logBaseOnTwo (5) = logBaseOnTwo (8) = 3, they two will be merged.*/<br />if (i == logBaseOnTwo (scan -> degree))<br />{<br />if (NULL == assistant[i])<br />assistant[i] = scan ;<br />else<br />{<br />temp = scan -> right ;<br />if (scan -> item < assistant[i] -> item)<br />{<br />cut (assistant[i]) ;<br />merge (scan, assistant[i]) ;<br />}<br />else<br />{<br />cut (scan) ;<br />merge (assistant[i], scan) ;<br />}<br />assistant[i] = NULL ;<br />}<br />}<br />scan = temp ;<br />}<br />while (scan != record)<br />;<br />}<br />free (assistant) ;<br />}</p><p>(*pfh) -> current-- ;</p><p>return return_value ;<br />}</p><p>/*Please make sure that pn is in *pfh before you use this function.*/<br />BOOL DecreaseKey_F (const FibonacciHeap * const pfh, Node * const pn, const int delta)<br />{<br />Node * parent ;</p><p>if (IsEmpty_F (pfh))<br />return FALSE ;<br />assert (pn != NULL) ;<br />assert (delta > 0) ;<br />pn -> item -= delta ;<br />if (pn -> parent != NULL && pn -> item < pn -> parent -> item)<br />{<br />parent = pn -> parent ;<br />renewDegree (parent, pn -> degree) ;<br />if (pn -> left == pn)<br />parent -> child = NULL ;<br />else<br />{<br />parent -> child = pn -> right ;<br />cut (pn) ;<br />}<br />pn -> parent = NULL ;<br />if (TRUE == pn -> index)<br />pn -> index = FALSE ;<br />link ((*pfh) -> min, pn) ;<br />if (TRUE == parent -> index)<br />findCascadingCutAndRenew (parent, (*pfh) -> min) ;<br />else<br />parent -> index = TRUE ;<br />}<br />if (pn -> item < (*pfh) -> min -> item)<br />(*pfh) -> min = pn ;</p><p>return TRUE ;<br />}</p><p>BOOL Delete_F (const FibonacciHeap * const pfh, Node * const pn)<br />{<br />if (IsEmpty_F (pfh))<br />return FALSE ;<br />/*For avert overflow, NEGATIVE_INFINTY is not the smallest number in 32 bits.*/<br />DecreaseKey_F (pfh, pn, NEGATIVE_INFINTY) ;<br />DeleteMin_F (pfh) ;</p><p>return TRUE ;<br />}</p><p>void Release_F (const FibonacciHeap * const pfh)<br />{<br />if ((*pfh) -> min != NULL)<br />release ((*pfh) -> min) ;<br />free (*pfh) ;<br />}</p><p>/*局部函數定義*/</p><p>static Node * makeNode (const Item * const pi)<br />{<br />Node * new_node ;</p><p>new_node = (Node *) malloc (sizeof (Node)) ;<br />if (NULL == new_node)<br />return NULL ;<br />new_node -> item = *pi ;<br />new_node -> degree = 1 ;<br />new_node -> index = FALSE ;<br />new_node -> left = new_node -> right = new_node ;<br />new_node -> parent = new_node -> child = NULL ;</p><p>return new_node ;<br />}</p><p>static int logBaseOnTwo (const int current)<br />{<br />int power, value ;</p><p>for (value = 1, power = 0; value < current; power++)<br />value <<= 1 ;</p><p>return power ;<br />}</p><p>/*Can't process if list is empty.*/<br />static void link (Node * list, Node * const new_node)<br />{<br />/*If there is only one node in list.*/<br />if (list == list -> right)<br />{<br />list -> left = list -> right = new_node ;<br />new_node -> left = new_node -> right = list ;<br />}<br />else<br />{<br />list -> right -> left = new_node ;<br />new_node -> left = list ;<br />new_node -> right = list -> right ;<br />list -> right = new_node ;<br />}<br />}</p><p>static void cut (Node * const gap)<br />{<br />gap -> left -> right = gap -> right ;<br />gap -> right -> left = gap -> left ;<br />}</p><p>static void merge (Node * const root, Node * const child)<br />{<br />child -> parent = root ;<br />root -> degree += child -> degree ;<br />if (NULL == root -> child)<br />{<br />child -> left = child -> right = child ;<br />root -> child = child ;<br />}<br />else<br />link (root -> child, child) ;<br />}</p><p>static void findCascadingCutAndRenew (Node * const pn, Node * const list)<br />{<br />Node * parent = pn -> parent ;</p><p>if (parent != NULL)<br />{<br />renewDegree (parent, pn -> degree) ;<br />if (1 == pn -> degree)<br />parent -> child = NULL ;<br />else<br />{<br />parent -> child = pn -> right ;<br />cut (pn) ;<br />}<br />pn -> parent = NULL ;<br />link (list, pn) ;<br />if (TRUE == parent -> index)<br />findCascadingCutAndRenew (parent, list) ;<br />else<br />parent -> index = TRUE ;<br />}<br />}</p><p>static void renewDegree (Node * const parent, const int degree)<br />{<br />assert (parent != NULL) ;<br />parent -> degree -= degree ;<br />if (parent -> parent != NULL)<br />renewDegree (parent -> parent, degree) ;<br />}</p><p>/*It is so skilful! I am a talent!*/<br />static void release (Node * const pn)<br />{<br />if (pn -> child != NULL)<br />release (pn -> child) ;<br />if (pn != pn -> right && pn -> right -> item != BE_RELEASED)<br />{<br />pn -> item = BE_RELEASED ;<br />release (pn -> right) ;<br />}<br />free (pn) ;<br />}