/** * Recurses up the tree to make a series of cascading cuts. Cuts each * node that has lost two children from its parent. * * @param queue Queue to which node belongs * @param node Node to cut */ static void cut_from_parent( fibonacci_heap *queue, fibonacci_node *node ) { fibonacci_node *next, *prev; if ( node->parent != NULL ) { next = node->next_sibling; prev = node->prev_sibling; next->prev_sibling = node->prev_sibling; prev->next_sibling = node->next_sibling; node->next_sibling = node; node->prev_sibling = node; node->parent->rank--; if ( node->parent->first_child == node ) { if ( node->parent->rank == 0 ) node->parent->first_child = NULL; else node->parent->first_child = next; } if ( node->parent->marked == FALSE ) node->parent->marked = TRUE; else cut_from_parent( queue, node->parent ); queue->minimum = append_lists( queue, node, queue->minimum ); node->parent = NULL; } else { if( node->key < queue->minimum->key ) queue->minimum = node; } }
fibonacci_node* pq_insert( fibonacci_heap *queue, item_type item, key_type key ) { fibonacci_node* wrapper = pq_alloc_node( queue->map, 0 ); ITEM_ASSIGN( wrapper->item, item ); wrapper->key = key; wrapper->next_sibling = wrapper; wrapper->prev_sibling = wrapper; queue->size++; queue->minimum = append_lists( queue, queue->minimum, wrapper ); return wrapper; }
node *quicksort(node *list) { node *first_node; /* first node */ node *list_sorted, *list_sorted_final; /* copied list */ node *list_left, *list_right, *sorted_list_left, *sorted_list_right; /* left and right side of original list */ node *item; /* variable used in for loop condition */ list_left = NULL; list_right = NULL; if (list == NULL || list->next == NULL) { list_sorted = copy_list(list); return list_sorted; } first_node = create_node(list->data, NULL); /* Copy the first node of list */ for (item = list->next; item != NULL; item = item->next) { if (item->data < first_node->data) { list_left = create_node(item->data, list_left); } else /* item >= first_node */ { list_right = create_node(item->data, list_right); } } sorted_list_left = quicksort(list_left); sorted_list_right = quicksort(list_right); list_sorted = append_lists(sorted_list_left, first_node); list_sorted_final = append_lists(list_sorted, sorted_list_right); free_list(list_left); free_list(list_right); free_list(sorted_list_left); free_list(sorted_list_right); free_list(list_sorted); free_list(first_node); assert(is_sorted(list_sorted_final)); return list_sorted_final; }
/** * Links two trees, making the item with lesser key the parent, breaking * ties arbitrarily. * * @param queue Queue to which roots belong * @param a First root * @param b Second root * @return The resulting merged tree */ static fibonacci_node* link( fibonacci_heap *queue, fibonacci_node *a, fibonacci_node *b ) { fibonacci_node *parent, *child; if ( b->key < a->key ) { parent = b; child = a; } else { parent = a; child = b; } // roots are automatically unmarked child->marked = FALSE; child->parent = parent; child->next_sibling = child; child->prev_sibling = child; parent->first_child = append_lists( queue, parent->first_child, child ); parent->rank++; return parent; }
key_type pq_delete( fibonacci_heap *queue, fibonacci_node *node ) { if( node == queue->minimum ) return pq_delete_min( queue ); key_type key = node->key; fibonacci_node *child = node->first_child; // remove from sibling list node->next_sibling->prev_sibling = node->prev_sibling; node->prev_sibling->next_sibling = node->next_sibling; if ( node->parent != NULL ) { node->parent->rank--; // if not a root, see if we need to update parent's first child if ( node->parent->first_child == node ) { if ( node->parent->rank == 0 ) node->parent->first_child = NULL; else node->parent->first_child = node->next_sibling; } if ( node->parent->marked == FALSE ) node->parent->marked = TRUE; else cut_from_parent( queue, node->parent ); } pq_free_node( queue->map, 0, node ); queue->size--; append_lists( queue, queue->minimum, child ); return key; }
/** * Merges two node lists into one to update the root system of the queue. * Iteratively links the roots such that no two roots of the same rank * remain. Assumes that the roots array is empty to begin with, and clears out * this array before completing execution. Breaks list of roots to simplify * insertion and linking, and rebuilds the circular list at the end. * * @param queue Queue to which the two lists belong * @param a First node list * @param b Second node list */ static void merge_and_fix_roots( fibonacci_heap *queue, fibonacci_node *a, fibonacci_node *b ) { fibonacci_node *start = append_lists( queue, a, b ); fibonacci_node *current, *next; int32_t i, rank; if ( start == NULL ) return; // break the circular list start->prev_sibling->next_sibling = NULL; start->prev_sibling = NULL; // insert an initial node queue->roots[start->rank] = start; queue->largest_rank = start->rank; start->parent = NULL; current = start->next_sibling; // insert the rest of the nodes while( current != NULL ) { // extract from the list next = current->next_sibling; if( next != NULL ) next->prev_sibling = NULL; current->next_sibling = NULL; current->parent = NULL; // insert into the registry while ( !attempt_insert( queue, current ) ) { rank = current->rank; current = link( queue, current, queue->roots[rank] ); queue->roots[rank] = NULL; } current = next; } // pick the largest tree out of the registry to start reforming the list start = queue->roots[queue->largest_rank]; queue->roots[queue->largest_rank] = NULL; queue->minimum = start; current = start; // pull the rest out and clear the registry for later use for ( i = queue->largest_rank - 1; i >= 0; i-- ) { if( queue->roots[i] != NULL ) { if( queue->roots[i]->key < queue->minimum->key ) queue->minimum = queue->roots[i]; current->prev_sibling = queue->roots[i]; queue->roots[i]->next_sibling = current; current = queue->roots[i]; queue->roots[i] = NULL; } } current->prev_sibling = start; start->next_sibling = current; queue->largest_rank = 0; }
/* * Does: Sorts a linked list using the quicksort algorithm. * Arguments: * -- list: A pointer to the first node of the linked list to * be sorted. * Returns: A pointer to the first node of the sorted linked list. */ node * quicksort(node *list) { node *first_node; node *left_half = NULL; node *sorted_left_half = NULL; node *right_half = NULL; node *sorted_right_half = NULL; node *head; node *sorted_list; node *sorted_list2; int pivot; int head_data; /* If a null list or single node, return a copy of it */ if (list == NULL || list->next == NULL) { return copy_list(list); } else /* Else, partition the list into left and right lists */ { first_node = copy_list(list); free_list(first_node->next); first_node->next = NULL; /* Value with which data fields are compared against */ pivot = first_node->data; head = list->next; while (head != NULL) { head_data = head->data; if (head_data < pivot) { /* Add nodes to left_half, creating the left_half list */ left_half = create_node(head_data, left_half); } else { /* Add nodes to right_half, creating the right_half list */ right_half = create_node(head_data, right_half); } head = head->next; } /* Sort the left_half recursively using quicksort */ sorted_left_half = quicksort(left_half); free_list(left_half); left_half = sorted_left_half; /* Sort the right_half recursively using quicksort */ sorted_right_half = quicksort(right_half); free_list(right_half); right_half = sorted_right_half; /* * Append the left and right halves with the first node in the * middle to create a sorted list. */ sorted_list = append_lists(left_half, first_node); sorted_list2 = append_lists(sorted_list, right_half); /* Free memory */ free_list(sorted_list); free_list(first_node); free_list(left_half); free_list(right_half); assert(is_sorted(sorted_list2)); return sorted_list2; } }