配对堆

来源:互联网 发布:域名需要几天 编辑:程序博客网 时间:2024/04/29 21:30

http://blog.csdn.net/ljsspace/article/details/6751900

配对堆:

一、特性:

配对堆是一种比较实用的斐波那契堆,它的优势是在进行DecreaseKey的时候速度快于其他堆结构。

1.在这里,每个顶点可以接很多的孩子,在这里的实现类似与二项队列。使用左孩子与兄弟

2. 加了一个Prev指针,指向前向节点,可以指向父亲,也可以指向兄弟。

其实现如下图所示:




二、基础操作:

这里最基础的操作就是合并堆,由于一个根节点可以接许多的孩子,我们合并的时候,只需要让较小的根节点成为父亲,较大的根成为左孩子即可。


编码实现:

合并:

[cpp] view plaincopy
  1. PairHeap CompareAndLink(PairHeap H1, PairHeap H2)  
  2. {  
  3.     if(H2 == NULL)  
  4.         return H1;  
  5.     else if(H1 ->Element <= H2->Element)  
  6.     {  
  7.         H2->Prev = H1;  
  8.         H1->NextSibling = H2->NextSibling;  
  9.         if(H1->NextSibling != NULL)  
  10.             H1->NextSibling->Prev = H1;  
  11.   
  12.         H2->NextSibling = H1->Left;  
  13.         if(H2->NextSibling != NULL)  
  14.             H2->NextSibling->Prev = H2;  
  15.   
  16.         H1->Left = H2;  
  17.         return H1;  
  18.     }  
  19.     else  
  20.     {  
  21.         H2->Prev = H1->Prev;  
  22.         H1->Prev = H2;  
  23.         H1->NextSibling = H2->Left;  
  24.   
  25.         if(H1->NextSibling != NULL)  
  26.             H1->NextSibling->Prev = H1;  
  27.         H2->Left = H1;  
  28.         return H2;  
  29.     }  
  30.   
  31. }  

插入:

[cpp] view plaincopy
  1. PairHeap insert(ElementType X, PairHeap H, Position * Loc)  
  2. {  
  3.     PairHeap NewNode;  
  4.     NewNode = (PairHeap)malloc(sizeof(struct PairNode));  
  5.     if(NewNode == NULL)  
  6.         exit(1);  
  7.   
  8.     NewNode->Element = X;  
  9.     NewNode->Left = NewNode->NextSibling = NewNode ->Prev = NULL;  
  10.   
  11.     *Loc = NewNode;  
  12.     if(H == NULL)  
  13.         return NewNode;  
  14.   
  15.     return CompareAndLink(H, NewNode);  
  16. }  

删除:

[cpp] view plaincopy
  1. PairHeap deleteMin(ElementType * Min, PairHeap H)  
  2. {  
  3.     if(H == NULL)  
  4.         return H;  
  5.   
  6.     PairHeap NewRoot;  
  7.     *Min = H->Element;  
  8.     if(H->Left != NULL)  
  9.         NewRoot = CombineSiblings(H->Left);  
  10.     free(H);  
  11.   
  12.     return NewRoot;  
  13. }  

[cpp] view plaincopy
  1. PairHeap CombineSiblings(Position FirstSibling)  
  2. {  
  3.     static Position TreeArray[100];  
  4.     int i, j, Num;  
  5.   
  6.     if(FirstSibling == NULL)  
  7.         return FirstSibling;  
  8.   
  9.     for(Num =0; FirstSibling != NULL; Num++)  
  10.     {  
  11.         TreeArray[Num] = FirstSibling;  
  12.         FirstSibling->Prev->NextSibling = NULL;  
  13.         FirstSibling = FirstSibling->NextSibling;  
  14.     }  
  15.   
  16.     TreeArray[Num] = NULL;  
  17.   
  18.     for(i =0; i+1<Num; i +=2)  
  19.         TreeArray[i] = CompareAndLink(TreeArray[i], TreeArray[i+1]);  
  20.   
  21.   
  22.     j =i-2;  
  23.     if(j == Num -3)  
  24.         TreeArray[j] = CompareAndLink(TreeArray[j], TreeArray[j+2]);  
  25.   
  26.     for(; j>=2; j-=2)  
  27.         TreeArray[j-2] = CompareAndLink(TreeArray[j-2], TreeArray[j]);  
  28.   
  29.       
  30.   
  31.     return TreeArray[0];  
  32. }  

减小键值:

[cpp] view plaincopy
  1. PairHeap DecreaseKey(Position P, ElementType Delta, PairHeap H)  
  2. {  
  3.     if(Delta < 0)  
  4.         return H;  
  5.     P->Element -= Delta;  
  6.   
  7.     if(P == H)  
  8.         return H;  
  9.       
  10.     if(P->NextSibling != NULL)  
  11.         P->NextSibling->Prev = P->Prev;  
  12.   
  13.     if(P->Prev->Left == P)  
  14.         P->Prev ->Left = P->NextSibling;  
  15.     else  
  16.         P->Prev->NextSibling = P->NextSibling;  
  17.   
  18.     P->NextSibling = NULL;  
  19.     return CompareAndLink(H, P);  
  20. }  

测试:


左图是插入节点之后,形成的配对堆,可见,只有0是根,其他的都是孩子。

右图是删除根节点0之后,形成的新配对堆。

0 0
原创粉丝点击