Fibonacci Heap实现参考

来源:互联网 发布:c语言取反!用法 编辑:程序博客网 时间:2024/05/16 07:19
/* File fheap.c - Fibonacci Heap* ----------------------------------------------------------------------------*  Shane Saunders*/#include <cstdlib>#include <cmath>#if FHEAP_DUMP#include <cstdio>#endif#include "fheap.h"/*--- FHeap (public methods) ------------------------------------------------*//* --- Constructor ---* Creates an FHeap object capable of holding up to $n$ items.*/FHeap::FHeap(int n){    int i;#if FHEAP_DUMPprintf("new, ");#endif    maxTrees = 1 + (int) (1.44 * log(n)/log(2.0));    maxNodes = n;    trees = new (FHeapNode *)[maxTrees];    for(i = 0; i < maxTrees; i++) trees[i] =0;    nodes = new (FHeapNode *)[n];    for(i = 0; i < n; i++) nodes[i] = 0;    itemCount = 0;    /* The $treeSum$ of the heap helps to keep track of the maximum rank while     * nodes are inserted or deleted.     */    treeSum = 0;    /* For experimental purposes, we keep a count of the number of key     * comparisons.     */    compCount = 0;#if FHEAP_DUMPprintf("new-exited, ");#endif}/* --- Destructor ---*/FHeap::~FHeap(){    int i;    #if FHEAP_DUMPprintf("delete, ");#endif    for(i = 0; i < maxNodes; i++) delete nodes[i];    delete [] nodes;    delete [] trees;    #if FHEAP_DUMPprintf("delete-exited, ");#endif}/* --- insert() ---* Inserts an item $item$ with associated key $k$ into the heap.*/void FHeap::insert(int item, long k){    FHeapNode *newNode;#if FHEAP_DUMPprintf("insert, ");#endif    /* create an initialise the new node */    newNode = new FHeapNode;    newNode->child = NULL;    newNode->left = newNode->right = newNode;    newNode->rank = 0;    newNode->item = item;    newNode->key = k;    /* maintain a pointer to $item$'s new node in the heap */    nodes[item] = newNode;    /* meld the new node into the heap */    meld(newNode);    /* update the heaps node count */    itemCount++;#if FHEAP_DUMPprintf("insert-exited, ");#endif}/* --- deleteMin() ---* Deletes and returns the minimum item from the heap.*/int FHeap::deleteMin(){    FHeapNode *minNode, *child, *next;    long k, k2;    int r, v, item;#if FHEAP_DUMPprintf("deleteMin, ");#endif    /* First we determine the maximum rank in the heap. */    v = treeSum;    r = -1;    while(v) {        v = v >> 1;        r++;    };    /* Now determine which root node is the minimum. */    minNode = trees[r];    k = minNode->key;    while(r > 0) {        r--;        next = trees[r];        if(next) {            if((k2 = next->key) < k) {                k = k2;                minNode = next;            }            compCount++;        }    }    /* We remove the minimum node from the heap but keep a pointer to it. */    r = minNode->rank;    trees[r] = NULL;    treeSum -= (1 << r);    child = minNode->child;    if(child) meld(child);    /* Record the vertex no of the old minimum node before deleting it. */    item = minNode->item;    nodes[item] = NULL;    delete minNode;    itemCount--;#if FHEAP_DUMPprintf("deleteMin-exited, ");#endif    return item;}/* --- decreaseKey() ---* Decreases the key used for item $item$ to the value newValue.  It is left* for the user to ensure that newValue is in-fact less than the current value*/void FHeap::decreaseKey(int item, long newValue){    FHeapNode *cutNode, *parent, *newRoots, *r, *l;    int prevRank;#if FHEAP_DUMPprintf("decreaseKey on vn = %d, ", item);#endif    /* Obtain a pointer to the decreased node and its parent then decrease the     * nodes key.     */    cutNode = nodes[item];    parent = cutNode->parent;    cutNode->key = newValue;    /* No reinsertion occurs if the node changed was a root. */    if(!parent) {#if FHEAP_DUMPprintf("decreaseKey-exited, ");#endif        return;    }    /* Update the left and right pointers of cutNode and its two neighbouring     * nodes.     */    l = cutNode->left;    r = cutNode->right;    l->right = r;    r->left = l;    cutNode->left = cutNode->right = cutNode;    /* Initially the list of new roots contains only one node. */    newRoots = cutNode;    /* While there is a parent node that is marked a cascading cut occurs. */    while(parent && parent->marked) {        /* Decrease the rank of cutNode's parent and update its child pointer.         */        parent->rank--;        if(parent->rank) {            if(parent->child == cutNode) parent->child = r;        }        else {            parent->child = NULL;        }        /* Update the cutNode and parent pointers to the parent. */        cutNode = parent;        parent = cutNode->parent;        /* Update the left and right pointers of cutNodes two neighbouring         * nodes.         */        l = cutNode->left;        r = cutNode->right;        l->right = r;        r->left = l;        /* Add cutNode to the list of nodes to be reinserted as new roots. */        l = newRoots->left;        newRoots->left = l->right = cutNode;        cutNode->left = l;        cutNode->right = newRoots;        newRoots = cutNode;    }    /* If the root node is being relocated then update the trees[] array.     * Otherwise mark the parent of the last node cut.     */    if(!parent) {        prevRank = cutNode->rank + 1;        trees[prevRank] = NULL;        treeSum -= (1 << prevRank);    }    else {        /* Decrease the rank of cutNode's parent an update its child pointer.         */        parent->rank--;        if(parent->rank) {            if(parent->child == cutNode) parent->child = r;        }        else {            parent->child = NULL;        }        parent->marked = 1;    }    /* Meld the new roots into the heap. */    meld(newRoots);#if FHEAP_DUMPprintf("decreaseKey-exited, ");#endif}/*--- FHeap (private methods) -----------------------------------------------*//* --- meld() ---* melds the linked list of trees pointed to by $treeList$ into the heap.*/void FHeap::meld(FHeapNode *treeList){    FHeapNode *first, *next, *nodePtr, *newRoot, *temp, *temp2, *lc, *rc;    int r;#if FHEAP_DUMPprintf("meld: ");#endif    /* We meld each tree in the circularly linked list back into the root level     * of the heap.  Each node in the linked list is the root node of a tree.     * The circularly linked list uses the sibling pointers of nodes.  This     *  makes melding of the child nodes from a deleteMin operation simple.     */    nodePtr = first = treeList;    do {#if FHEAP_DUMPprintf("%d, ", nodePtr->item);#endif        /* Keep a pointer to the next node and remove sibling and parent links         * from the current node.  nodePtr points to the current node.         */        next = nodePtr->right;        nodePtr->right = nodePtr->left = nodePtr;        nodePtr->parent = NULL;        /* We merge the current node, nodePtr, by inserting it into the         * root level of the heap.         */        newRoot = nodePtr;        r = nodePtr->rank;        /* This loop inserts the new root into the heap, possibly restructuring         * the heap to ensure that only one tree for each degree exists.         */        do {            /* Check if there is already a tree of degree r in the heap.             * If there is then we need to link it with newRoot so it will be             * reinserted into a new place in the heap.             */            if((temp = trees[r])) {           /* temp will be linked to newRoot and relocated so we no                 * longer will have a tree of degree r.                 */                trees[r] = NULL;                treeSum -= (1 << r);           /* Swap temp and newRoot if necessary so that newRoot always                 * points to the root node which has the smaller key of the                 * two.                 */           if(temp->key < newRoot->key) {                    temp2 = newRoot;                    newRoot = temp;                    temp = temp2;                }                compCount++;                /* Link temp with newRoot, making sure that sibling pointers                 * get updated if rank is greater than 0.  Also, increase r for                 * the next pass through the loop since the rank of new has                 * increased.                 */           if(r++ > 0) {                    rc = newRoot->child;                    lc = rc->left;                    temp->left = lc;                    temp->right = rc;                    lc->right = rc->left = temp;                }                newRoot->child = temp;                newRoot->rank = r;                temp->parent = newRoot;                temp->marked = 0;            }            /* Otherwise if there is not a tree of degree r in the heap we             * allow newRoot, which possibly carries moved trees in the heap,             * to be a tree of degree r in the heap.             */            else {                trees[r] = newRoot;                treeSum += (1 << r);;                /* NOTE:  Because newRoot is now a root we ensure it is                 *        marked.                 */                newRoot->marked = 1;       }            /* Note that temp will be NULL if and only if there was not a tree             * of degree r.             */        } while(temp);        nodePtr = next;    } while(nodePtr != first);#if FHEAP_DUMPprintf("meld-exited, ");#endif}/*--- FHeap (debugging) -----------------------------------------------------*//* --- dumpNodes() ---* Recursively print a text representation of the node subtree starting at the* node poined to by $node$, using an indentationlevel of $level$.*/void FHeap::dumpNodes(FHeapNode *node, int level){#if FHEAP_DUMP     FHeapNode *childNode, *partner;     int i, childCount;     /* Print leading whitespace for this level. */     for(i = 0; i < level; i++) printf("   ");     printf("%d(%ld)[%d]\n", node->item, node->key, node->rank);          if((childNode = node->child)) {    childNode = node->child->right;             childCount = 0;         do {             dumpNodes(childNode, level+1);        if(childNode->dim > node->dim) {                 for(i = 0; i < level+1; i++) printf("   ");       printf("error(dim)\n");  exit(1);        }        if(childNode->parent != node) {                 for(i = 0; i < level+1; i++) printf("   ");       printf("error(parent)\n");        }             childNode = childNode->right;        childCount++;         } while(childNode != node->child->right);         if(childCount != node->dim) {        for(i = 0; i < level; i++) printf("   ");             printf("error(childCount)\n");  exit(1);         }     }     else {          if(node->dim != 0) {             for(i = 0; i < level; i++) printf("   ");        printf("error(dim)\n"); exit(1);    }     }#endif}/* --- dump() ---* Print a text representation of the heap to the standard output.*/void FHeap::dump() const{#if FHEAP_DUMP    int i;    FHeapNode *node;    printf("\n");    printf("treeSum = %d\n", treeSum);    printf("array entries 0..maxTrees =");    for(i = 0; i < maxTrees; i++) {        printf(" %d", trees[i] ? 1 : 0 );    }    printf("\n\n");    for(i = 0; i < maxTrees; i++) {        if((node = trees[i])) {            printf("tree %d\n\n", i);            dumpNodes(node, 0);       printf("\n");        }    }    fflush(stdout);#endif    }
原创粉丝点击