最小二项堆

来源:互联网 发布:手机淘宝退款怎么取消 编辑:程序博客网 时间:2024/05/21 09:54

最小二项堆:



1. 节点的关键字(key)大于或等于父节点的关键字.

2. degree表示子女的个数

3. slibing指向紧右的兄弟结点,最右节点的slibing为NIL.

4. 二项堆的根节点组织成一个链表(有slibing连接): 根表

5. parent指向父节点,根节点的parent为NIL

6.child指向左边第一个子节点

7. head指向度数(degree)最小的节点,根表的度数严格递增,不能有相同degree的节点父节点

8.






#include <stdio.h>#include <stdlib.h>#include <string.h>#define  INT_MAX    0x7FFFFFFF #define  INT_MIN    (-INT_MAX - 1)//#define  NULL   0#define  false  0#define  true   1typedef struct BinomialHeapNode{  int                    key;  int                    degree; //本节点子女的个数  struct BinomialHeapNode     *parent;  /*指向父节点*/  struct BinomialHeapNode     *child;   /*指向子节点*/  /*指向紧右的兄第节点,右边紧挨着的兄弟节点;如果为根节点,则指向下一个根节点*/  struct BinomialHeapNode     *sibling;    void*                 satellite;     /*the satellite data keep in the node*/}BinomialHeapNode;typedef BinomialHeapNode    *BinomialHeap;typedef BinomialHeapNode    *BinoNode_point;BinomialHeapNode* MakeBinomialHeap(){         BinomialHeapNode*  BinoHeap = NULL;     BinoHeap = (BinomialHeapNode*)malloc(sizeof(BinomialHeapNode));     if(NULL == BinoHeap)     {          printf("malloc failed %s, %d \n", __FILE__, __LINE__);          return NULL;     }     BinoHeap->child = NULL;     BinoHeap->degree = 0;     BinoHeap->parent = NULL;     BinoHeap->sibling = NULL;     BinoHeap->satellite = NULL;          return BinoHeap;     }/************************************************************************ * BinomialHeapMinimum * *  get the node of  least key in the heap;    go through the root list of Binomial Heap and find the least key  * @heap   the head of heap * * return: the node of the least key in the heap ************************************************************************/BinomialHeapNode* BinomialHeapMinimum(BinomialHeap heap){    BinoNode_point x = heap, y = NULL;    int      min = INT_MAX;    while(NULL != x)    {         /*go through the root list of Binomial Heap and find the least key*/        if(x->key < min)        {            min = x->key;            y = x;        }        x = x->sibling;            }    return y;    }/******************************************************************************BinomialLink**Link two Binomial heap with same degree, the the second will be the father  after the link,  note: the input parameter should not be NULL;** @heap1  the heap1 will be the child of heap2 after the link* @heap2  the heap2 will be the parent of heap1 aftre the link ******************************************************************************/void BinomialLink(BinomialHeap heap1, BinomialHeap heap2){     heap1->parent = heap2;         /*set heap2 as the parent of heap1 */     heap1->sibling = heap2->child; /*set the heap2's child as heap1's sibling*/     heap2->child = heap1;          /*set the heap1 as heap2 child*/     heap2->degree++;     return;}/*******************************************************************************BinomialHeapMerge  Merge the root lists of two Heap in the order of degree of the root node.*@H1 the first Heap which is merged in the heap*@H2 the second heap which is merged in the heap*return the new heap the H1 and H2 after been merged.*****************************************************************************/BinomialHeap BinomialHeapMerge(BinomialHeap H1, BinomialHeap H2){    BinomialHeap heap = NULL;    BinoNode_point      firstNode = NULL, secondNode = NULL, pre_H3 = NULL, H3 = NULL;      if((H1 != NULL) && (H2 != NULL))    {         firstNode = H1;         secondNode = H2;         while((firstNode != NULL) && (secondNode != NULL))         {             //那个node的degree小就将H3指向那个node             if(firstNode->degree <= secondNode->degree)             {                 H3 = firstNode;                 firstNode = firstNode->sibling;                              }             else             {                 H3 = secondNode;                 secondNode = secondNode->sibling;                              }             if(NULL == pre_H3)             {                 pre_H3 = H3;                 heap = H3;             }             else             {                 pre_H3->sibling = H3; //将小的node插入到已排好序的链表                 pre_H3 = H3; //将H3暂时保存到pre_H3用于后续将sibling连到H3             }             //将H3的sibling连接到下一个非空的node(除非两个都是NULL)             if(firstNode != NULL)             {                 H3->sibling = firstNode;               }             else             {                 H3->sibling = secondNode;             }          }        }    else if(H1 != NULL)    {        heap = H1;    }    else if(H2 != NULL)     {        heap = H2;    }    else    {        heap = NULL;    }    return heap;}/*******************************************************************************BinomialHeapUnion  There are two stage in BinomialHeapUnion:   1.  Call BinomialHeapMerge to merge the root link of two heap in order of       the degree of root nodes.  2.  Link the roots which have same degrees until all roots' degrees are different.  *@H1 the first Heap which is united in the heap*@H2 the second heap which is united in the heap*return the new heap the H1 and H2 after been united.*****************************************************************************/BinomialHeap BinomialHeapUnion(BinomialHeap H1, BinomialHeap H2){    BinomialHeap heap = NULL;    BinoNode_point      x = NULL, pre_x = NULL, next_x = NULL;    heap = BinomialHeapMerge(H1, H2); /*Merge two root links*/    if(NULL == heap)        return NULL;    x = heap;    next_x = x->sibling;    while(NULL != next_x)    {        if((x->degree != next_x->degree) ||  /*case 1: 两个连续的node degree不同,跳过到下一个*/             ((next_x->sibling != NULL)&&(x->degree == next_x->sibling->degree)))/*case2:上个连续的node degree都相同, 跳过后到了下次循环时会进入到case3 or case4*/        {            pre_x = x;            x = next_x;        }        else if(x->key <= next_x->key) //case 3. The key of x is smaller, link next_x to x, so the sibling of x will link to the sibling of next_x        {            x->sibling = next_x->sibling;            BinomialLink(next_x, x);        }        else //case 4.         {            if(NULL == pre_x) /*first loop of key of x is bigger than next_x*/            {                heap = next_x;            }            else            {                pre_x->sibling = next_x;            }            BinomialLink(x, next_x);            x = next_x;        }        next_x = x->sibling;    }    return heap;    }/*******************************************************************************BinomialHeapInsert  Inset a Node in to the heap    *@H the Heap which the node will be inserted*@node the Node which is inserted in the heap*return the new heap the after the node had been inserted*****************************************************************************/BinomialHeap BinomialHeapInsert(BinomialHeap H, BinomialHeapNode* node){    BinomialHeap  heap, heapret = NULL;    if(NULL == node)    {         printf("Input parameter node is null %s, %d \n", __FILE__, __LINE__);         return H;    }    node->parent = NULL;    node->child = NULL;    node->sibling = NULL;    node->degree = 0;    heap = node;    heapret = BinomialHeapUnion(H, heap);    return heapret;    }/*******************************************************************************BinomialHeapExtractMin  Extract the Min key Node from Heap    *@H [in/out]the  Heap which the node will be extracted.**return the min key node extracted from the heap*****************************************************************************/BinomialHeapNode* BinomialHeapExtractMin(BinomialHeap* H){    BinoNode_point    x = *H, y = NULL, pre_y = NULL, p;    BinomialHeap H2 = NULL;    int         minkey;    minkey = INT_MAX;    if(NULL == *H)    {        printf("Input parameter heap is null %s, %d \n", __FILE__, __LINE__);         return NULL;    }    /*get the min key node and set it to y*/    while(x != NULL)    {        if(x->key < minkey)        {            minkey = x->key;            pre_y = y;            y = x;        }        x = x->sibling;    }    if (y == NULL)    {        return NULL;    }        if(NULL == pre_y) /*if the min key node is the first node of the list */    {        *H = (*H)->sibling;  /*remove y from the list*/    }    else    {        pre_y->sibling = y->sibling;  /*remove y from the list*/    }    x = y->child;    /*reverse the order of the linked list of the children of the min key node*/    while(NULL != x)    {        p = x;        x = x->sibling;        p->sibling = H2;        H2 = p;        p->parent = NULL;            }        *H = BinomialHeapUnion(*H, H2);    return y;    }/******************************************************************************BinomialHeapDecreaseKeydecrease the key of node x to the input newkey@H Heap which include the node x, the x should in the heap@x The node x which key value will be decrease to newkey@newkey the newkey value of x after decreasereturn: if success, return true, else return false******************************************************************************/int  BinomialHeapDecreaseKey(BinomialHeap H, BinomialHeapNode* x, int newkey){    BinoNode_point  y, z;    int temp;    void* tempsatellite;        if(newkey > x->key)    {       printf("new key(%d) is greaer than current key %s, %d \n", newkey, __FILE__, __LINE__);        return false;    }    x->key = newkey;    y = x;    z = y->parent;    while((NULL != z) && (z->key > y->key))    {        temp = y->key;        y->key = z->key;        z->key = temp;        tempsatellite = y->satellite;        y->satellite = z->satellite;        z->satellite = tempsatellite;        y = z;        z = y->parent;            }    return true;    }/******************************************************************************BinomialHeapDeletedecrease the key of node x to the input newkey@H Heap which include the node x, the x should in the heap@x The node x which   will be deletedreturn: the deleted node******************************************************************************/BinomialHeapNode* BinomialHeapDelete(BinomialHeap H,  BinomialHeapNode* x){    BinomialHeapDecreaseKey(H, x, INT_MIN);    return BinomialHeapExtractMin(&H);}/******************************************************************************BinomialHeapFindByKeysearch the node whose key value is equal to key@H Heap which want to search@key The key value of the node which want to searchreturn: if finded, return the node, else return NULL******************************************************************************/BinomialHeapNode* BinomialHeapFindByKey(BinomialHeap H, int key){    BinoNode_point  p = NULL, x = NULL;    p = H;    while(NULL != p)    {        if(key == p->key)        {          return p;        }        if(NULL !=(x = BinomialHeapFindByKey(p->child, key)))        {            return x;        }                /*The searching of pre root finish, search the next root*/        p = p->sibling;    }        return NULL;    }/******************************************************************************BinomialHeapDeleteByKeydecrease the key of node x to the input newkey@H  The heap want to be delete the node whose key value equal the key @key the key is used to indentify the the delete nodereturn: the deleted node, but the key had been updated******************************************************************************/BinomialHeapNode* BinomialHeapDeleteByKey(BinomialHeap* H,  int key){    BinoNode_point x = NULL;    x = BinomialHeapFindByKey(*H, key);    if(NULL == x)    {         printf("The key(%d) is not in the heap %s, %d \n", key, __FILE__, __LINE__);          return *H;    }    BinomialHeapDecreaseKey(*H, x, INT_MIN);    return BinomialHeapExtractMin(H);}void BinomialHeapPrint(BinomialHeap H){     BinoNode_point  p = NULL;          if(NULL == H)     {         printf("The heap is NULL %s, %d \n", __FILE__, __LINE__);          return;     }     p = H;     while(NULL != p)     {         printf("(");         printf("%d ", p->key);         if(NULL != p->child)         {              BinomialHeapPrint(p->child);         }         printf(") ");         p = p->sibling;            }     return;     }//用数组内的值建堆BinomialHeap MakeBinHeapWithArray(int keys[], int n){    BinomialHeap heap = NULL, newHeap = NULL;    int i;    for ( i = 0; i < n; i++)    {        newHeap = (BinomialHeap) malloc(sizeof(BinomialHeapNode));        if (newHeap == NULL)        {            printf("malloc failed %s, %d \n", __FILE__, __LINE__);            exit(1);        }        memset(newHeap, 0, sizeof(BinomialHeapNode));        newHeap->key = keys[i];        if (NULL == heap)        {            heap = newHeap;        }        else        {            heap = BinomialHeapUnion(heap, newHeap);            newHeap = NULL;        }    }    return heap;}int kp1[8] = {12,              7, 25,              15, 28, 33, 41             };int kp2[20] = {18,               3, 37,               6, 8, 29, 10, 44, 30, 23, 2, 48, 31, 17, 45, 32, 24, 50, 55              };int kp4[23] = {37, 41,               10, 28, 13, 77,               1, 6, 16, 12, 25, 8, 14, 29, 26, 23, 18, 11, 17, 38, 42, 27              };int main(){    BinomialHeap H1 = NULL;    H1 = MakeBinHeapWithArray(kp1, 7);    printf("The first Binomial Heap H1\n");    BinomialHeapPrint(H1);    BinomialHeap H2 = NULL;    H2 = MakeBinHeapWithArray(kp2, 19);    printf("The Second Binomial Heap H2\n");    BinomialHeapPrint(H2);    BinomialHeap H3 = NULL;    H3 = BinomialHeapUnion(H1, H2);    printf("\n\n The Union Heap H3 after United H1, H2 \n");    BinomialHeapPrint(H3);    BinomialHeap H4 = NULL;    H4 = MakeBinHeapWithArray(kp4, 22);    printf("\n\n The H4 used for test extract and delet node from H4\n");    BinomialHeapPrint(H4);    BinomialHeap extractNode = BinomialHeapExtractMin(&H4);    if (extractNode != NULL)    {        printf("\n\n after extract the min from H4  %d \n", extractNode->key);        BinomialHeapPrint(H4);        free(extractNode);    }        extractNode = BinomialHeapExtractMin(&H4);    if (extractNode != NULL)    {        printf("\n\n after extract the minum from H4 %d \n", extractNode->key);        BinomialHeapPrint(H4);        free(extractNode);    }    extractNode = BinomialHeapExtractMin(&H4);        if (extractNode != NULL)    {        printf("\n\n after extract the minum from H4 %d \n", extractNode->key);        BinomialHeapPrint(H4);        free(extractNode);    }        extractNode = BinomialHeapDeleteByKey(&H4, 12);    if(NULL != extractNode)    {        extractNode->key = 12;        printf("\n\n after delete %d from H4 \n", extractNode->key);        BinomialHeapPrint(H4);        free(extractNode);            }    printf("\n");    return 0;}





原创粉丝点击