/**
 * 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;
}
예제 #3
0
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;
}
예제 #7
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;
    }
}