二項堆的實現

#include <stdio.h>
#include <stdlib.h>

#define SUCCESS 1
#define FAIL 0

struct bheap
{
    struct bheap* parent;
    long key;
    int degree;
    struct bheap* child;
    struct bheap* sibling;
};
typedef struct bheap bheap_node;
typedef struct bheap bheap_head;

void print(const int array[], int size);
bheap_node* creat_bheap_node();
void delete_bheap(bheap_head* head);
bheap_head* insert_bheap_node(bheap_head* head, bheap_node* node);
bheap_head* union_bheap(bheap_head* head1,bheap_head* head2);
bheap_head* merge_bheap(bheap_head* head1,bheap_head* head2);
void print_heap(bheap_head* head);
bheap_head* link_bheap(bheap_head* head1, bheap_head* head2);
bheap_node* get_biggest_bheap_node(bheap_head* head);
bheap_head* fetch_biggest_bheap_node(bheap_head* head);
void desrease_bheap_node_key(bheap_node* node, long new_key);
bheap_head* deleteb_bheap_node(bheap_head* head, bheap_node* del_node);

void print(const int array[], int size)
{
    int index = 0;
    while(index < size)
    {
        printf("%d ",array[index]);
        index++;
    }
    printf("\n");
}

bheap_node* creat_bheap_node()
{
    bheap_node* node = (bheap_node*)malloc(sizeof(bheap_node));

    if(NULL != node)
    {
        node->parent = NULL;
        node->key = 0;
        node->degree = 0;
        node->child = NULL;
        node->sibling = NULL;
    }
    return node;
}


void delete_bheap(bheap_head* head)
{
    bheap_node* node = head;

    if(NULL == head)
        return ;
    do
    {
        if(NULL != head->child)//Child
        {
            node = head->child;
            head->child = NULL;
            head = node;
        }
        else if(NULL == head->child)//No Child
        {

            if(NULL != head->sibling)//Sibling
            {
                node = head->sibling;
            }
            else//No Sibling
                node = head->parent;
            free(head);
            head = node;
        }
    }while((NULL != head->child)||(NULL != head->sibling) || (NULL != head->parent));

    free(head);
}

bheap_head* insert_bheap_node(bheap_head* head, bheap_node* node)
{
    return union_bheap(head,node);
}

bheap_head* union_bheap(bheap_head* head1,bheap_head* head2)
{
    bheap_head* head;
    bheap_head* pre_node;
    bheap_head* curr_node;
    bheap_head* next_node;

    head = merge_bheap(head1, head2);

    if(NULL == head)
        return NULL;

    pre_node = NULL;
    curr_node = head;
    next_node = head->sibling;

    while(NULL != next_node)
    {
        if((curr_node->degree != next_node->degree) || ((NULL != next_node->sibling)&&(next_node->sibling->degree == curr_node->degree)))
        {
            pre_node = curr_node;
            curr_node = next_node;
        }
        else if(curr_node->key > next_node->key)
        {
            curr_node->sibling = next_node->sibling;
            curr_node = link_bheap(next_node, curr_node);
        }
        else if(curr_node->key <= next_node->key)
        {
            if(NULL == pre_node)
                head = next_node;
            else
                pre_node->sibling = next_node;
            next_node = link_bheap(curr_node,next_node);
            curr_node = next_node;
        }

        next_node = curr_node->sibling;
    }
    return head;
}

bheap_head* merge_bheap(bheap_head* head1,bheap_head* head2)
{
    bheap_head* head;
    bheap_head* node;
    bheap_head* smaller_node;
    bheap_head* bigger_node;
    int index = 0;

    while((NULL != head1) && (NULL != head2))
    {
        if(head1->degree == head2->degree)
        {
            if(head1->key <= head2->key)
            {
                smaller_node = head1;
                bigger_node = head2;
            }
            else
            {
                smaller_node = head2;
                bigger_node = head1;
            }

            head1 = head1->sibling;
            head2 = head2->sibling;

            smaller_node->sibling = bigger_node;
        }
        else if(head1->degree > head2->degree)
        {
            bigger_node = smaller_node = head2;
            head2 = head2->sibling;
        }
        else
        {
            bigger_node = smaller_node = head1;
            head1 = head1->sibling;
        }

        if(0 == index)
            head = smaller_node;
        else
            node->sibling = smaller_node;

        node = bigger_node;

        index++;
    }

    if(NULL == head1)
    {
        if(0 == index)
            head = head2;
        else
            node->sibling = head2;
    }
    else//NULL == head2
    {
        if(0 == index)
            head = head1;
        else
            node->sibling = head1;
    }

    return head;
}

void print_heap(bheap_head* head)
{
    bheap_node* node;
    int ret_parent = 0;

    if(NULL == head)
    {
        printf("bheap: NULL\n");
        return ;
    }


    node = head;
    do
    {
        if((0 == ret_parent) && (NULL != node->child))
        {
            node = node->child;
        }
        else if((0 == ret_parent)  && (NULL == node->child))
        {
            printf("Node key: %ld; degree: %d\n", node->key,node->degree);
            if(NULL != node->sibling)
            {
                node = node->sibling;
                ret_parent = 0;
            }
            else
            {
                node = node->parent;
                if(NULL == node)
                    return;
                ret_parent = 1;
            }
        }
        else if(1 == ret_parent)
        {
            printf("Node key: %ld; degree: %d\n", node->key,node->degree);
            if(NULL != node->sibling)
            {
                node = node->sibling;
                ret_parent = 0;
            }
            else
            {
                node = node->parent;
                ret_parent = 1;
            }
        }
    }while((ret_parent == 0) || (NULL != node->sibling) || (NULL != node->parent));

    printf("Node key: %ld; degree: %d\n", node->key,node->degree);
}

bheap_head* link_bheap(bheap_head* head1, bheap_head* head2)
{
        head1->parent = head2;
        head1->sibling = head2->child;
        head2->child = head1;
        head2->degree ++;

        return head2;
}

bheap_node* get_biggest_bheap_node(bheap_head* head)
{
    bheap_node* node = head;
    long max;
    bheap_node* biggest_node;

    if(NULL == head)
        return NULL;
    max =  head->key;

    while(NULL != node)
    {
        if(node->key >= max)
        {
            max = node->key;
            biggest_node = node;
        }
        node = node->sibling;
    }

    return biggest_node;
}

bheap_head* fetch_biggest_bheap_node(bheap_head* head)
{
    bheap_head* head_after_fetch;
    bheap_head* head_changed_biggest_node;
    bheap_head* head_before_biggest_node;
    bheap_head* head_after_biggest_node;
    bheap_head* biggest_node;
    bheap_node* curr_node;
    bheap_node* pre_node;
    bheap_node* tmp_node;

    if(NULL == head)
        return NULL;

    head_after_fetch = NULL;
    head_changed_biggest_node = NULL;
    head_before_biggest_node = NULL;
    head_after_biggest_node = NULL;
    biggest_node = get_biggest_bheap_node(head);

    curr_node = biggest_node;
    pre_node = NULL;
    tmp_node = NULL;

    if(NULL == curr_node)
        return NULL;

    if(NULL == curr_node->child)
    {
        head_after_fetch = curr_node->sibling;
        curr_node->sibling = NULL;
        return head_after_fetch;
    }

    curr_node = curr_node->child;
    while(NULL != curr_node->sibling)
    {
        if(NULL == pre_node)
        {
            pre_node = curr_node;
            curr_node= curr_node->sibling;
            pre_node->sibling = NULL;
            pre_node->parent = NULL;
        }
        else
        {
            tmp_node = curr_node;
            curr_node = curr_node->sibling;
            tmp_node->sibling = pre_node;
            pre_node = tmp_node;
            pre_node->parent = NULL;
        }
    }

    curr_node->sibling = pre_node;
    curr_node->parent = NULL;

    head_changed_biggest_node = curr_node;

    biggest_node->child = NULL;

    tmp_node = head;
    while(NULL != tmp_node)
    {
        if(tmp_node == head && tmp_node == biggest_node)
        {
            head_before_biggest_node = NULL;
            head_after_biggest_node = biggest_node->sibling;
            biggest_node->sibling = NULL;

            break;
        }
        if(tmp_node->sibling == biggest_node)
        {
            head_before_biggest_node = head;
            tmp_node->sibling = NULL;
            head_after_biggest_node = biggest_node->sibling;
            biggest_node->sibling = NULL;
            break;
        }

        tmp_node = tmp_node->sibling;
    }

    head_after_fetch = union_bheap(head_before_biggest_node, head_changed_biggest_node);

    head_after_fetch = union_bheap(head_after_fetch,head_after_biggest_node);

    return head_after_fetch;
}

void desrease_bheap_node_key(bheap_node* node, long new_key)
{
    long tmp_key;
    if(NULL == node)
    {
        printf("Error: node is NULL!\n");
        return ;
    }
    if(new_key <= node->key)
    {
        printf("Error: new_key not more than node's key!\n");
        return;
    }

    node->key = new_key;
    while((NULL != node->parent) && (node->parent->key < node->key))
    {
        tmp_key = node->parent->key;
        node->parent->key = node->key;
        node->key = tmp_key;
        node = node->parent;
    }
}

bheap_head* deleteb_bheap_node(bheap_head* head, bheap_node* del_node)
{
    bheap_node* biggest_bheap_node = get_biggest_bheap_node(head);

    long new_key = biggest_bheap_node->key + 1;

    desrease_bheap_node_key(del_node, new_key);

    head = fetch_biggest_bheap_node(head);

    return head;
}

int main()
{
    int array[10] = {6,2,-2,8,3,5,4,0,9,1};
    int index = 0;
    //unchanged array
    printf("unchanged array: ");
    print(array, 10);

    //Creat bheap
    bheap_head* head;
    bheap_node* node;
    bheap_node* biggest_bheap_node;
    //long new_key = 10;

    while(index < 10)
    {
        node = creat_bheap_node();

        if(0 == index)
            head = node;

        if(NULL == node)
        {
            printf("Malloc Error: bheap node == NULL!\n");
            break;
        }

        node->key = array[index];

        if(index != 0)
            head = insert_bheap_node(head,node);

        index ++;
    }

    print_heap(head);

    //search the biggest node

    biggest_bheap_node = get_biggest_bheap_node(head);

    printf("Biggest Node key: %ld; degree: %d\n", biggest_bheap_node->key,biggest_bheap_node->degree);
/*
    head = fetch_biggest_bheap_node(head);

    printf("After 1' fetch:\n");
    print_heap(head);

    biggest_bheap_node = get_biggest_bheap_node(head);

    printf("Biggest Node key: %ld; degree: %d\n", biggest_bheap_node->key,biggest_bheap_node->degree);

    head = fetch_biggest_bheap_node(head);

    printf("After 2' fetch:\n");
    print_heap(head);

    biggest_bheap_node = get_biggest_bheap_node(head);

    printf("Biggest Node key: %ld; degree: %d\n", biggest_bheap_node->key,biggest_bheap_node->degree);

    head = fetch_biggest_bheap_node(head);

    printf("After 3' fetch:\n");
    print_heap(head);

    biggest_bheap_node = get_biggest_bheap_node(head);

    printf("Biggest Node key: %ld; degree: %d\n", biggest_bheap_node->key,biggest_bheap_node->degree);

    head = fetch_biggest_bheap_node(head);

    printf("After 4' fetch:\n");
    print_heap(head);

    biggest_bheap_node = get_biggest_bheap_node(head);

    printf("Biggest Node key: %ld; degree: %d\n", biggest_bheap_node->key,biggest_bheap_node->degree);

    head = fetch_biggest_bheap_node(head);

    printf("After 5' fetch:\n");
    print_heap(head);

    biggest_bheap_node = get_biggest_bheap_node(head);

    printf("Biggest Node key: %ld; degree: %d\n", biggest_bheap_node->key,biggest_bheap_node->degree);

    head = fetch_biggest_bheap_node(head);

    printf("After 6' fetch:\n");
    print_heap(head);

    biggest_bheap_node = get_biggest_bheap_node(head);

    printf("Biggest Node key: %ld; degree: %d\n", biggest_bheap_node->key,biggest_bheap_node->degree);

    head = fetch_biggest_bheap_node(head);

    printf("After 7' fetch:\n");
    print_heap(head);

    biggest_bheap_node = get_biggest_bheap_node(head);

    printf("Biggest Node key: %ld; degree: %d\n", biggest_bheap_node->key,biggest_bheap_node->degree);

    head = fetch_biggest_bheap_node(head);

    printf("After 8' fetch:\n");
    print_heap(head);

    biggest_bheap_node = get_biggest_bheap_node(head);

    printf("Biggest Node key: %ld; degree: %d\n", biggest_bheap_node->key,biggest_bheap_node->degree);

    head = fetch_biggest_bheap_node(head);

    printf("After 9' fetch:\n");
    print_heap(head);

    biggest_bheap_node = get_biggest_bheap_node(head);

    printf("Biggest Node key: %ld; degree: %d\n", biggest_bheap_node->key,biggest_bheap_node->degree);

    head = fetch_biggest_bheap_node(head);

    printf("After 10' fetch:\n");
    print_heap(head);
*/
    node = head->sibling->child->child;

    head = deleteb_bheap_node(head, node);

    print_heap(head);

    biggest_bheap_node = get_biggest_bheap_node(head);

    printf("Biggest Node key: %ld; degree: %d\n", biggest_bheap_node->key,biggest_bheap_node->degree);

    delete_bheap(head);

    return 0;
}

二項堆的講解見《算法導論》中第19章內容,實現如下,與原文中稍有差別,原文要求是最小二項堆,我實現的是最大二項堆,另外部分測試內容、相關注釋沒有寫:


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章