配对堆

 

配对堆(Pairing Heap)

分类: 数据结构和算法   5096人阅读  评论(0)  收藏  举报

配对堆(Pairing Heap)是一个简单实用的min-heap结构(当然也可以做成max-heap)。它是一颗多路树(multiway tree),类似于Leftist Heap和Skew Heap,但是与Binomial Tree和Fibonacci Heap不一样。它的基本操作是两个多路树的连接(link),所以取名叫Pairing Heap。连接操作(参考以下实现中的方法linkPair)类似于Binomial Tree和Fibonacci Heap中的link操作,即将root key值最大的树作为key值最小的树的孩子(一般作为最左边的孩子,特别是Binomial Heap必须这样做),其复杂度是常数级。因为Pairing Heap只有一棵树,所以它的merge操作(类似于Fibonacci Heap中的union)也很简单,只需要link两棵树就可以了,平摊复杂度与Fibonacci Heap类似,都是常数级操作,而在Binomial Heap中需要union两个root lists,所以复杂度为O(logn)。在算法分析中,往往有很多数据结构实现起来比较简单,但是分析起来很复杂,例如快速排序(Quicksort),配对堆也是一个典型例子。配对堆的merge,insert和findMin的平摊复杂度都是O(1),extract-min的平摊复杂度是O(logn),这与Fibonacci Heap中的相应操作的复杂度相当。但是,decrease-key的平摊复杂度比Fibonacci Heap大,后者的decrease-key的平摊复杂度是O(1)。关于配对堆的decrease-key操作的平摊复杂度结果可以参考:http://en.wikipedia.org/wiki/Pairing_heap。

在以下实现中,Pairing Heap采用“leftmost child,right sibling”(左孩子,右兄弟)方式表示,而且每一个结点还有一个left属性:对于第一个孩子,left属性表示该孩子的父结点;对于其他结点,left属性表示该结点的左兄弟。Extract-Min操作比较有意思,首先采用类似Binomial Heap和Fibonacci Heap中做法,即先删除root结点,然后得到root的孩子结点双向链表,链表中每一个结点对应一个子堆(subheap);接下来考虑如何将子堆合并到原来的堆中,在这里可以比较一下二项堆,Fibonacci堆和配对堆的合并做法:在Binomial Heap中将孩子结点倒排,生成按degree从小到大顺序的单向链表,然后将该单链表跟原来剩余的堆结点root list链表作union操作。在Fibonacci Heap中的做法是,将孩子结点依次添加到root list中(不用考虑先后次序),然后通过consolidate生成degree唯一的双向循环链表。二者都是在Extract-min时让每个堆结构变得更加紧凑,恢复成理想的状态,同时Extract-min的操作成本也相对比较高。在Pairing Heap中做法类似:如果没有Extract-min操作,其他的操作(比如insert,merge,decrease-key)势必使得root结点的孩子链表变得很长,通过Extract-Min两两合并,让Pairing Heap变得更加有序。Extract-Min两两合并做法是:先从左到右将相邻的孩子结点两两link,生成一个缩减的双向链表,然后对该新的双向链表从右到左link(上一次合并的结果作为下一次link中的右兄弟结点)。


实现:

[java]  view plain copy
  1. /** 
  2.  *  
  3.  * Pairing Heap    
  4.  *   
  5.  * Copyright (c) 2011 ljs (http://blog.csdn.net/ljsspace/) 
  6.  * Licensed under GPL (http://www.opensource.org/licenses/gpl-license.php)  
  7.  *  
  8.  * @author ljs 
  9.  * 2011-09-06 
  10.  * 
  11.  */  
  12. public class PairingHeap {  
  13.     //left-child, right-sibling representation  
  14.     static class Node{  
  15.         private int key;   
  16.           
  17.         //left is the parent for first child; is the left sibling for other children  
  18.         private Node left;        
  19.           
  20.         private Node sibling;     
  21.           
  22.         //child points to the leftmost-child   
  23.         private Node child;  
  24.                    
  25.         public Node(int key){  
  26.             this.key = key;  
  27.         }  
  28.         public String toString(){  
  29.             return String.valueOf(this.key);  
  30.         }  
  31.     }  
  32.       
  33.     private Node root;  
  34.       
  35.     private Node linkPair(Node first,Node second){  
  36.         if(second==nullreturn first;  
  37.         if(first==nullreturn second;  
  38.           
  39.         if(first.key<second.key){  
  40.             //second is linked to first as a child  
  41.               
  42.             //retain the sibling relation  
  43.             Node secondzSibling = second.sibling;  
  44.             first.sibling = secondzSibling;  
  45.             if(secondzSibling != null) secondzSibling.left = first;  
  46.               
  47.             Node firstzChild = first.child;  
  48.               
  49.             //update second's left and sibling pointers  
  50.             second.left = first;  
  51.             second.sibling = firstzChild;  
  52.               
  53.             //update first.child's pointer  
  54.             if(firstzChild != null) firstzChild.left = second;  
  55.               
  56.             //update first's child  
  57.             first.child = second;  
  58.             return first;  
  59.         }else{  
  60.             //first is linked to second as a child  
  61.               
  62.             //retain the sibling relation  
  63.             Node firstzLeft = first.left;  
  64.             second.left = firstzLeft;  
  65.             if(firstzLeft != null){  
  66.                 if(firstzLeft.child == first){  
  67.                     //firstzLeft is first's parent  
  68.                     firstzLeft.child = second;  
  69.                 }else{  
  70.                     //firstzLeft is first's left sibling                      
  71.                     firstzLeft.sibling = second;  
  72.                 }  
  73.             }             
  74.               
  75.             Node secondzChild = second.child;  
  76.             //update first's left and sibling pointers  
  77.             first.left = second;  
  78.             first.sibling = secondzChild;  
  79.               
  80.             //update second's child pointer  
  81.             if(secondzChild != null) secondzChild.left = first;  
  82.               
  83.             //update second's child  
  84.             second.child = first;  
  85.             return second;  
  86.         }  
  87.     }  
  88.     public Node insert(Node node){  
  89.         if(root==null)   
  90.             root = node;  
  91.         else  
  92.             root = linkPair(node,root);  
  93.         return node;  
  94.     }  
  95.       
  96.     public void decreaseKey(Node x,int k) throws Exception{  
  97.         if(x.key<k) throw new Exception("key is not decreased!");  
  98.         x.key = k;  
  99.         if(x!=root){  
  100.             //cut x subtree from its siblings  
  101.             Node xzLeft = x.left;   
  102.             //if x is not root, its left (i.e. xzLeft) can never be null  
  103.             if(xzLeft.child==x){//xzLeft is x's parent  
  104.                 xzLeft.child = x.sibling;                 
  105.             }else{//xzLeft is x's left sibling  
  106.                 xzLeft.sibling = x.sibling;  
  107.             }  
  108.             if(x.sibling!=null){  
  109.                 x.sibling.left = xzLeft;  
  110.             }  
  111.               
  112.             //merge this tree with x subtree  
  113.             x.left = null;  
  114.             x.sibling = null;  
  115.             root = this.linkPair(x, root);  
  116.         }  
  117.     }  
  118.       
  119.     public void merge(Node rhs){  
  120.         if(this.root==null) {  
  121.             this.root = rhs;  
  122.             return;  
  123.         }  
  124.         if(rhs==nullreturn;  
  125.           
  126.         this.root = this.linkPair(this.root, rhs);  
  127.     }  
  128.     public Node findMin(){  
  129.         return this.root;  
  130.     }  
  131.       
  132.     public Node extractMin(){  
  133.         Node z = this.root;  
  134.         if(z!=null){  
  135.             if(z.child==null)  
  136.                 root = null;  
  137.             else{  
  138.                 Node firstSibling = z.child;  
  139.                 firstSibling.left = null;                 
  140.                 root = mergeSubHeaps(firstSibling);  
  141.             }  
  142.         }  
  143.         return z;  
  144.     }  
  145.       
  146.     private Node mergeSubHeaps(Node firstSibling){  
  147.         //the 1st pass: merge pairs from left side  
  148.         Node first = firstSibling;  
  149.         Node second = first.sibling;  
  150.                   
  151.         Node tail = first;  
  152.         if(second!=null){  
  153.             tail = this.linkPair(first, second);  
  154.             first = tail.sibling;  
  155.             if(first!= null)  
  156.                 second = first.sibling;  
  157.             else  
  158.                 second = null;  
  159.         }  
  160.         while(first != null && second!=null){             
  161.             tail = this.linkPair(first, second);  
  162.             first = tail.sibling;  
  163.             if(first!= null)  
  164.                 second = first.sibling;       
  165.             else  
  166.                 second = null;  
  167.         }  
  168.           
  169.         //the 2nd pass: merge pairs from right side  
  170.         if(first!=null){  
  171.             tail = first;  
  172.         }  
  173.           
  174.         Node prev = tail.left;  
  175.         while(prev!=null){  
  176.             tail = this.linkPair(prev, tail);  
  177.             prev = tail.left;  
  178.         }  
  179.         return tail;  
  180.     }  
  181.     public void print(){  
  182.         System.out.println("Pairing Heap:");  
  183.         this.print(0this.root);  
  184.     }  
  185.       
  186.     private void print(int level, Node node){  
  187.         for (int i = 0; i < level; i++) {  
  188.             System.out.format(" ");  
  189.         }  
  190.         System.out.format("|");  
  191.         for (int i = 0; i < level; i++) {  
  192.             System.out.format("-");  
  193.         }  
  194.         System.out.format("%d%n", node.key);  
  195.         Node child = node.child;  
  196.         while(child!=null){           
  197.             print(level + 1, child);  
  198.             child = child.sibling;  
  199.         }             
  200.     }  
  201.     public static void main(String[] args) throws Exception {  
  202.         PairingHeap pheap = new PairingHeap();  
  203.         Node node7=pheap.insert(new Node(7));  
  204.         pheap.insert(new Node(19));  
  205.         Node node2=pheap.insert(new Node(2));  
  206.           
  207.         PairingHeap pheap2 = new PairingHeap();  
  208.         pheap2.insert(new Node(9));  
  209.         pheap2.insert(new Node(17));  
  210.         pheap2.insert(new Node(12));  
  211.         pheap2.insert(new Node(14));          
  212.         pheap.merge(pheap2.root);  
  213.           
  214.         pheap2 = new PairingHeap();  
  215.         pheap2.insert(new Node(15));  
  216.         pheap2.insert(new Node(18));  
  217.         pheap2.insert(new Node(16));  
  218.         pheap2.insert(new Node(5));  
  219.         Node node11=pheap2.insert(new Node(11));          
  220.         pheap.merge(pheap2.root);  
  221.           
  222.         pheap2 = new PairingHeap();  
  223.         pheap2.insert(new Node(4));  
  224.         pheap2.insert(new Node(8));       
  225.         pheap.merge(pheap2.root);  
  226.           
  227.         pheap2 = new PairingHeap();  
  228.         Node node3=pheap2.insert(new Node(3));  
  229.         pheap2.insert(new Node(13));  
  230.         pheap2.insert(new Node(10));  
  231.         pheap.merge(pheap2.root);  
  232.           
  233.         pheap.insert(new Node(6));  
  234.           
  235.         pheap.print();  
  236.           
  237.         Node min = pheap.findMin();  
  238.         System.out.format("min: %d%n", min.key);  
  239.           
  240.         pheap.decreaseKey(node11, 0);  
  241.         pheap.decreaseKey(node7, 4);  
  242.         pheap.decreaseKey(node2, 1);  
  243.         pheap.decreaseKey(node3, 2);  
  244.           
  245.         min = pheap.extractMin();  
  246.         while(min!=null){  
  247.             System.out.format("%d ",min.key);  
  248.             min = pheap.extractMin();         
  249.         }  
  250.     }  
  251.   
  252. }  

测试输出:

Pairing Heap:
|2
 |-6
 |-3
  |--10
  |--13
 |-4
  |--8
 |-5
  |--11
  |--15
   |---16
   |---18
 |-9
  |--14
  |--12
  |--17
 |-7
  |--19
min: 2
0 1 2 4 4 5 6 8 9 10 12 13 14 15 16 17 18 19 

用PairingHeap改进Dijkstra算法

浏览次数:1676次  2012年03月24日  华夏35度  字号:   

Dijkstra的计算过程就是在维护一张表,形如:

v known d p
v1 T 0 0
v2 F 2 v1
v3 F 3 v4
v4 T 1 v1
v5 F 3 v4
v6 F 9 v4
v7 F 5 v4

每一次循环要从d中找出最小者,于是PairHeap、FibHeap、BinaryHeap等等就派上用场了。本文我们采用PariHeap,至于为什么请看链接3。当需要更改(减小)d的值时,需要从PairHeap上找到相应的节点再执行DecreaseKey操作,于是我在链接2的基础之上为PairHeap增加了Find操作。

base.h

list.h

list.c

#include"list.h"
  
static  LTNode *makeNode(const  Item item)
{
    LTNode *newNode;
    newNode = (LTNode *) malloc(sizeof(struct  ltnode));
    newNode->item = item;
    newNode->next = NULL;
    return  newNode;
}
  
static  void  releaseNode(LTNode * const  p)
{
    if  (p != NULL) {
        releaseNode(p->next);
        free(p);
    }
}
  
/*创建并初始化单向链表*/
BOOL  Initialize_L(LinkedList * const  llh)
{
    (*llh) = (struct  linkedList *) malloc(sizeof(struct  linkedList));
    (*llh)->head = NULL;
    (*llh)->size = 0;
    return  TRUE;
}
  
/*确定一个单向链表是否为空*/
BOOL  IsEmpty_L(const  LinkedList * const  llh)
{
    if  ((*llh)->size == 0)
        return  TRUE;
    else
        return  FALSE;
}
  
/*向单向链表头部添加一个元素*/
BOOL  Insert_L(const  LinkedList * const  llh, const  Item item)
{
    LTNode *newNode = makeNode(item);
    if  ((*llh)->size == 0)
        (*llh)->head = newNode;
    else  {
        newNode->next = (*llh)->head;
        (*llh)->head = newNode;
    }
    (*llh)->size++;
    return  TRUE;
}
  
/*释放单向链表占用的空间*/
void  Release_L(LinkedList * const  llh)
{
    releaseNode((*llh)->head);
    free(*llh);
}

pairheap.h

#ifndef _PAIRHEAP_H
#define _PAIRHEAP_H
  
#include"base.h"
  
typedef  struct  phnode {
    Item item;
    struct  phnode *left, *previous, *nextSibling;
} PHNode;
  
typedef  struct  pairingHeap {
    PHNode *root;
    int  current;
} *PairingHeap;
  
/*创建并初始化配对堆*/
BOOL  Initialize_P(PairingHeap * const  pph);
  
/*确定一个配对堆是否为空*/
BOOL  IsEmpty_P(const  PairingHeap * const  pph);
  
/*向配对堆中插入一个数据为指定数据的结点.localizer用来传递回新节点的地址*/
BOOL  Insert_P(const  PairingHeap * const  pph, const  Item item);
  
/*在配对堆上查找数据点*/
PHNode* Find_P(const  PairingHeap * const  pph, const  Item item);
  
/*将配对堆中指定节点的数据降低delta*/
BOOL  DecreaseKey_P(const  PairingHeap * const  pph, PHNode * const  position,
           const  ValueType delta);
  
/*删除配对堆中数据域最小的节点,并通过pmin将其携带回调用该函数的函数*/
BOOL  DeleteMin_P(const  PairingHeap * const  pph, Item * const  pmin);
  
/*打印堆*/
void  Print_P(const  PairingHeap * const  pph);
  
/*释放配对堆占用的空间*/
void  Release_P(PairingHeap * const  pph);
  
#endif

pairheap.c

#include"pairheap.h"
  
/*全局变量声明*/
static  PHNode *NullNode = NULL;
  
/*局部函数声明*/
static  PHNode *compareAndLink_P(PHNode * const  first, PHNode * const  second);
static  PHNode *makeNode_P(const  Item item);
static  PHNode *combineSiblings_P(PHNode * firstSibling);
static  void  release_P(PHNode * const  pn);
static  PHNode *find(PHNode * const  root, const  Item item);
static  void  printNode(const  PHNode * const  root);
  
/*局部函数定义*/
static  PHNode *compareAndLink_P(PHNode * const  first, PHNode * const  second)
{
    if  (second == NullNode)
        return  first;
    if  (second->item.dist < first->item.dist) {    /*把first作为second的最左子孩子 */
        second->previous = first->previous;
        first->previous = second;
        first->nextSibling = second->left;
        first->nextSibling->previous = first;
        second->left = first;
        return  second;
    else  {        /*把second作为first的最左孩子 */
        second->previous = first;
        first->nextSibling = second->nextSibling;
        first->nextSibling->previous = first;
        second->nextSibling = first->left;
        second->nextSibling->previous = second;
        first->left = second;
        return  first;
    }
}
  
static  PHNode *makeNode_P(const  Item item)
{
    PHNode *newNode;
    newNode = (PHNode *) malloc(sizeof(PHNode));
    if  (NULL == newNode)
        return  NULL;
    newNode->item = item;
    newNode->left = newNode->nextSibling = newNode->previous = NullNode;
    return  newNode;
}
  
static  PHNode *combineSiblings_P(PHNode * firstSibling)
{
    static  PHNode *treeArray[MAXSIBLINGS];  /*treeArray是个一维数组,每个元素是Node*类型。静态成员在编译时就要初始化,所以数组长度必须是已知的。给treeArray分配一个足够大的长度,再定义为静态的(全局生命周期),每次调用函数时都使用这一个treeArray,省去过多的重复初始化 */
    int  i, j, numSiblings;
    /*如果只有一个孩子,则直接返回它 */
    if  (firstSibling->nextSibling == NullNode)
        return  firstSibling;
    /*把所有兄弟放在treeArray中 */
    for  (numSiblings = 0; firstSibling != NullNode; numSiblings++) {
        treeArray[numSiblings] = firstSibling;
        /*打断双向链表中每个节点向后的指针 */
        firstSibling->previous->nextSibling = NullNode;
        firstSibling = firstSibling->nextSibling;
    }
    treeArray[numSiblings] = NullNode;  //一定要把最后一个设为NullNode,因为treeArray的总长度为MAXSIBLINGS,NullNode之前的才是有效元素
    /*从左向右两两合并子树 */
    //printf("第一趟合并: ");
    for  (i = 0; i + 1 < numSiblings; i += 2){
        treeArray[i] = compareAndLink_P(treeArray[i], treeArray[i + 1]);
        //printf("一次");
        //printNode(treeArray[i]);
    }
    j = i - 2;
    if  (j == numSiblings - 3){  /*兄弟有奇数个 */
        treeArray[j] = compareAndLink_P(treeArray[j], treeArray[j + 2]);
        //printf("合并最一个奇数项");
        //printNode(treeArray[j]);
    }
    /*进行第二趟合并 */
    /*从右向左逐个合并 */
    //printf("第二趟合并: ");
    while  (j >= 2) {
        treeArray[j - 2] =
            compareAndLink_P(treeArray[j - 2], treeArray[j]);
        //printf("一次");
        //printNode(treeArray[j-2]);
        j -= 2;
    }
    return  treeArray[0];
}
  
static  void  release_P(PHNode * const  pn)
{
    if  (pn != NullNode) {
        release_P(pn->left);
        release_P(pn->nextSibling);
        free(pn);
    }
}
  
static  PHNode *find(PHNode * const  root, const  Item item)
{
    //printf("开始查找vindex=%d\tdist=%d\n",root->item.vindex,(int)root->item.dist);
    if(root==NullNode)
        return  NullNode;
    else  if(root->item.vindex==item.vindex)
        return  root;
    else  if(item.dist<root->item.dist)
        return  find(root->nextSibling,item);
    else{
        PHNode *rect;
        return  ((rect=find(root->nextSibling,item))==NullNode)?find(root->left,item):rect;/*先搜兄弟节点;如果找不到,再搜孩子节点;如果还找不到则返回NullNode*/
    }
}
  
static  void  printNode(const  PHNode * const  root)
{
    if(root==NullNode){
        printf("\t");
        return;
    }
    else{
        printf("%d(%d)\t",root->item.vindex,(int)root->item.dist);
        printf("%d's next:",root->item.vindex);printNode(root->nextSibling);
        printf("%d's left:",root->item.vindex);printNode(root->left);
    }
}
  
/*************************************接口函数定义********************************/
BOOL  Initialize_P(PairingHeap * const  pph)
{
    if  (NullNode == NULL) {
        NullNode = (PHNode *) malloc(sizeof(PHNode));
        if  (NullNode == NULL) {
            puts("Out of space.");
            return  FALSE;
        }
        *pph = (struct  pairingHeap *)malloc(sizeof(struct  pairingHeap));
        if  (*pph == NULL) {
            puts("Out of space");
            free(NullNode);
            NullNode == NULL;
            return  FALSE;
        }
        NullNode->left = NullNode->previous = NullNode->nextSibling = NullNode;
        (*pph)->root = NullNode;
        (*pph)->current = 0;
    }
    return  TRUE;
}
  
BOOL  IsEmpty_P(const  PairingHeap * const  pph)
{
    switch  ((*pph)->current) {
    case  0:
        return  TRUE;
    default:
        return  FALSE;
    }
}
  
BOOL  Insert_P(const  PairingHeap * const  pph, const  Item item)
{
    PHNode *newNode;
    newNode = makeNode_P(item);
    if  (newNode == NULL) {
        puts("out of space.");
        return  FALSE;
    }
    //*localizer = newNode;
    if  (IsEmpty_P(pph) == TRUE)
        (*pph)->root = newNode;
    else
        (*pph)->root = compareAndLink_P((*pph)->root, newNode);
    (*pph)->current++;
    return  TRUE;
}
  
PHNode *Find_P(const  PairingHeap * const  pph, const  Item item)
{
    //printf("调用Find_P\n");
    PHNode * rect=find((*pph)->root,item);
    if(rect==NullNode)
        return  NULL;
    else{
        return  rect;
    }
}
  
BOOL  DecreaseKey_P(const  PairingHeap * const  pph, PHNode * const  position,
           const  ValueType delta)
{
    if  (delta <= 0)
        return  FALSE;
    //printf("要把%d降低%d\n",position->item.vindex,(int)delta);
    position->item.dist -= delta;
    //printf("降低节点值以后:vindex=%d\tdist=%d\n",position->item.vindex,(int)position->item.dist);
    if  (position == (*pph)->root)
        return  TRUE;    /*如果减小的是根节点的值,可以直接返回 */
    /*把position从堆上(双向链表中)取下来 */
    position->nextSibling->previous = position->previous;
    if  (position->previous->left == position) /*position是最左孩子 */
        position->previous->left = position->nextSibling;
    else
        position->previous->nextSibling = position->nextSibling;
    position->nextSibling = NullNode;
    /*再把position合并到堆的根节点上去*/
    (*pph) -> root = compareAndLink_P ((*pph) -> root, position) ;
    return  TRUE;
}
  
BOOL  DeleteMin_P(const  PairingHeap * pph, Item * const  pmin)
{
    PHNode *newRoot;
    if  (IsEmpty_P(pph))
        return  FALSE;
    else  {
        newRoot = NullNode;
        *pmin = (*pph)->root->item;
        if  ((*pph)->root->left != NullNode)
            newRoot = combineSiblings_P((*pph)->root->left);
        free((*pph)->root);
        (*pph)->root = newRoot;
        (*pph)->current--;
        return  TRUE;
    }
}
  
void  Print_P(const  PairingHeap * const  pph)
{
    if((*pph)->root==NullNode)
        return;
    else
        printNode((*pph)->root);
    printf("\n");
}
  
void  Release_P(PairingHeap * const  pph)
{
    release_P((*pph)->root);
    free(*pph);
    free(NullNode);
    NullNode = NULL;
}

dijkstra.c

 
#include"list.h"
#include"pairheap.h"
#include<time.h>
#include<limits.h>
  
typedef  struct   {
    int  vindex;
    BOOL  known;
    ValueType dist;
    int  preindex;
}TableLine;
  
typedef  struct  {
    int  vindex;
    LinkedList neighbours;
} Adjancent;
  
char  *vertexName[] = { "V1""V2""V3""V4""V5""V6""V7"  };
  
void  InitResultTable(TableLine resultTable[],int  len){
    int  i;
    for(i=0;i<len;i++){
        resultTable[i].vindex=i;
        resultTable[i].known=FALSE;
        resultTable[i].dist=INT_MAX;
        resultTable[i].preindex=-1;
    }
}
  
/*根据最终的TableLine打印到各节点的最短路径*/
void  printShortWay(TableLine resultTable[],int  len){
    int  i;
    for(i=0;i<len;i++){
        printf("%s: ",vertexName[resultTable[i].vindex]);
        double  way=resultTable[i].dist;
        int  curline=i;
        do{
            int  p=resultTable[curline].preindex;
            if(p!=-1)
                printf("%s\t",vertexName[p]);
            //else
                //printf("END\t");
        }while((curline=resultTable[curline].preindex)!=-1);
        printf("总路程:%d\n",(int)way);
    }
}
  
/*初始化带权有向图*/
void  InitGraph(Adjancent **graph)
{
    LinkedList *list0;list0=(LinkedList *)malloc(sizeof(LinkedList));Initialize_L(list0);
    Item item1;item1.vindex=1;item1.dist=2;Insert_L(list0, item1);
    Item item2;item2.vindex=3;item2.dist=1;Insert_L(list0, item2);
    Adjancent *adj0;adj0=(Adjancent *)malloc(sizeof(Adjancent));adj0->vindex = 0;adj0->neighbours = *list0;graph[0]=adj0;
      
    LinkedList *list1;list1=(LinkedList *)malloc(sizeof(LinkedList));Initialize_L(list1);
    Item item3;item3.vindex=3;item3.dist=3;Insert_L(list1, item3);
    Item item4;item4.vindex=4;item4.dist=10;Insert_L(list1, item4);
    Adjancent *adj1;adj1=(Adjancent *)malloc(sizeof(Adjancent));adj1->vindex = 1;adj1->neighbours = *list1;graph[1]=adj1;
      
    LinkedList *list2;list2=(LinkedList *)malloc(sizeof(LinkedList));Initialize_L(list2);
    Item item5;item5.vindex=0;item5.dist=4;Insert_L(list2, item5);
    Item item6;item6.vindex=5;item6.dist=5;Insert_L(list2, item6);
    Adjancent *adj2;adj2=(Adjancent *)malloc(sizeof(Adjancent));adj2->vindex = 2;adj2->neighbours = *list2;graph[2]=adj2;
      
    LinkedList *list3;list3=(LinkedList *)malloc(sizeof(LinkedList));Initialize_L(list3);
    Item item7;item7.vindex=2;item7.dist=2;Insert_L(list3, item7);
    Item item8;item8.vindex=4;item8.dist=2;Insert_L(list3, item8);
    Item item9;item9.vindex=5;item9.dist=8;Insert_L(list3, item9);
    Item item10;item10.vindex=6;item10.dist=4;Insert_L(list3, item10);
    Adjancent *adj3;adj3=(Adjancent *)malloc(sizeof(Adjancent));adj3->vindex = 3;adj3->neighbours = *list3;graph[3]=adj3;
      
    LinkedList *list4;list4=(LinkedList *)malloc(sizeof(LinkedList));Initialize_L(list4);
    Item item11;item11.vindex=6;item11.dist=6;Insert_L(list4, item11);
    Adjancent *adj4;adj4=(Adjancent *)malloc(sizeof(Adjancent));adj4->vindex = 4;adj4->neighbours = *list4;graph[4]=adj4;
      
    LinkedList *list5;list5=(LinkedList *)malloc(sizeof(LinkedList));Initialize_L(list5);
    Adjancent *adj5;adj5=(Adjancent *)malloc(sizeof(Adjancent));adj5->vindex = 5;adj5->neighbours = *list5;graph[5]=adj5;
      
    LinkedList *list6;list6=(LinkedList *)malloc(sizeof(LinkedList));Initialize_L(list6);
    Item item12;item12.vindex=5;item12.dist=1;Insert_L(list6, item12);
    Adjancent *adj6;adj6=(Adjancent *)malloc(sizeof(Adjancent));adj6->vindex = 6;adj6->neighbours = *list6;graph[6]=adj6;
}
  
/*以领接表的形式打开带权有向图*/
void  printGraph(Adjancent **graph){
    int  i, j;
    LTNode *neighbour;
    for  (i = 0; i < VERTEXNUM; i++) {
        printf("%s\t", vertexName[graph[i]->vindex]);
        neighbour = graph[i]->neighbours->head;
        int  len = graph[i]->neighbours->size;
        while  (len-- > 0) {
            printf("%s(%d)\t", vertexName[neighbour->item.vindex],
                   (int)(neighbour->item.dist));
            neighbour = neighbour->next;
        }
        printf("\n");
    }
}
  
int  main()
{
    Adjancent **graph;
    graph = (Adjancent **) malloc(sizeof(Adjancent *) * VERTEXNUM);
    InitGraph(graph);
    printGraph(graph);
      
    TableLine resultTable[VERTEXNUM];
    InitResultTable(resultTable,VERTEXNUM);
      
    PairingHeap * pph;
    pph=(PairingHeap *)malloc(sizeof(PairingHeap));
    Initialize_P(pph);
      
    int  startindex=0;       /*指定起点*/
    resultTable[startindex].dist=0;
      
    int  i;
    for(i=0;i<VERTEXNUM;++i){
        Item item;
        item.vindex=i;
        if(i!=startindex)
            item.dist=INT_MAX;
        else
            item.dist=0;
        Insert_P(pph,item);
    }
    //printf("初始化堆后: ");
    //Print_P(pph);
      
    while(1){
        Item *pmin;
        pmin=(Item*)malloc(sizeof(Item));
        if(DeleteMin_P(pph,pmin)==FALSE){       /*从配对堆上取下最小元素*/
            break;
        }
        //printf("取下最小元素后: ");
        //Print_P(pph);
        int  index=pmin->vindex;
        resultTable[index].known=TRUE;
        double  cvw=resultTable[index].dist;
        LTNode *neighbour= graph[index]->neighbours->head;
        int  len = graph[index]->neighbours->size;
        while  (len-- > 0) {
            int  ind=neighbour->item.vindex;
            if(resultTable[ind].known==FALSE){
                double  d=neighbour->item.dist;
                if(d+cvw<resultTable[ind].dist){
                    Item fi;
                    fi.vindex=ind;
                    fi.dist=resultTable[ind].dist;
                    PHNode *change=Find_P(pph,fi);
                    if(change==NULL){
                        fprintf(stderr,"在配对堆上找不到要找的项.vindex=%d\tdist=%d\n",fi.vindex,(int)fi.dist);
                        free(change);
                        exit(1);
                    }
                    //printf("change:vindex=%d\tdist=%d\n",change->item.vindex,(int)change->item.dist);
                    DecreaseKey_P(pph,change,resultTable[ind].dist-d-cvw);
                    //printf("降低元素值后: ");
                    //Print_P(pph);
                    resultTable[ind].dist=d+cvw;
                    resultTable[ind].preindex=index;
                }
            }
            neighbour = neighbour->next;
        }
    }
      
    printShortWay(resultTable,VERTEXNUM);
    Release_P(pph);
    for(i=0;i<VERTEXNUM;++i){
        Release_L(&(graph[i]->neighbours));
    }
    return  0;
}

提供几个链接
  1. PairingHeap算法讲得不错
  2. PairingHeap的C语言实现
  3. BinaryHeap, FibHeap, PairHeap对改进Dijkstra的性能比较

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值