📄 dijkstra.cpp
字号:
//***************************************************************************// FIBTEST.CPP//// Test program for the F-heap implementation.// Copyright (c) 1996 by John Boyer.// See header file for free usage information.//***************************************************************************#include <math.h>#include "mex.h"extern void _main();#include <stdlib.h>#include <iostream.h>#include <stdio.h>#include <conio.h>#include <ctype.h>#include <memory.h>#include <time.h>#include "fibheap.h"#define _FIBHEAP_CPP//***************************************************************************// This Fibonacci heap implementation is Copyright (c) 1996 by John Boyer.// See the header file for free usage information.//***************************************************************************//***************************************************************************// The classes in this package are designed to allow the package user// to quickly and easily develop applications that require a heap data// structure. Using amortized analysis, the asymptotically fastest heap// data structure is the Fibonacci heap. The constants are a little// high so the real speed gain will not be seen until larger data sets// are required, but in most cases, if the data set is small, then the// run-time will be neglible anyway.//// To use this heap class you need do only two things. First, subclass// the FibHeapNode class to create the class of objects that you'd// like to store in a heap. Second, create an instance of the FibHeap// class, which can then be used to Insert(), ExtractMin(), etc.,// instances of your FibHeapNode subclass. Notice that you don't need// to create a subclass of the FibHeap class.//// The application-specific data object that you'd like to store in a heap// will have a key value. In the class that you derive from FibHeapNode,// you will need to define the key structure then provide assignment (=),// equality (==) and less-than operators and a destructor. These functions// are declared virtual so that the code in the FibHeap class can compare,// assign and destroy your objects by calling on your code.//// The overloaded operators in your defined class MUST call functions in// the Fibonacci heap node class first. For assignment, the function// FHN_Assign() should be called before code that deals with the copy of// the key value. For comparison operators, the function FHN_Cmp() should// appear first. If it returns 0, then keys can be compared as normal.// The following indicates what the three most common operators must do// based on the return value of FHN_Cmp() //// For ==, if zero returned, then compare keys// if non-zero X returned, then return 0// For <, if zero returned, then compare keys// if non-zero X returned, then return X<0?1:0// For >, if zero returned, then compare keys// if non-zero X returned, then return X>0?1:0 //***************************************************************************#include <stdlib.h>#include <iostream.h>#include <stdio.h>#include <conio.h>#include "fibheap.h"//***************************************************************************//=========================================================// FibHeapNode Constructor//=========================================================//***************************************************************************FibHeapNode::FibHeapNode(){ Left = Right = Parent = Child = NULL; Degree = Mark = NegInfinityFlag = 0;}//=========================================================// FibHeapNode Destructor//// Body is empty, but declaration is required in order to// force virtual. This will ensure that FibHeap class// calls derived class destructors.//=========================================================FibHeapNode::~FibHeapNode(){}//=========================================================// FHN_Assign()//// To be used as first step of an assignment operator in a// derived class. The derived class will handle assignment// of key value, and this function handles copy of the// NegInfinityFlag (which overrides the key value if it is// set).//=========================================================void FibHeapNode::FHN_Assign(FibHeapNode& RHS){ NegInfinityFlag = RHS.NegInfinityFlag;}//=========================================================// FHN_Cmp()//// To be used as the first step of ALL comparators in a// derived class.//// Compares the relative state of the two neg. infinity// flags. Note that 'this' is the left hand side. If// LHS neg. infinity is set, then it will be less than (-1)// the RHS unless RHS neg. infinity flag is also set.// Only if function returns 0 should the key comparison// defined in the derived class be performed, e.g.//// For ==, if zero returned, then compare keys// if non-zero X returned, then return 0// For <, if zero returned, then compare keys// if non-zero X returned, then return X<0?1:0// For >, if zero returned, then compare keys// if non-zero X returned, then return X>0?1:0 //=========================================================int FibHeapNode::FHN_Cmp(FibHeapNode& RHS){ if (NegInfinityFlag) return RHS.NegInfinityFlag ? 0 : -1; return RHS.NegInfinityFlag ? 1 : 0; }//========================================================================// We do, on occasion, compare and assign objects of type FibHeapNode, but// only when the NegInfinityFlag is set. See for example FibHeap::Delete().//// Also, these functions exemplify what a derived class should do.//========================================================================void FibHeapNode::operator =(FibHeapNode& RHS){ FHN_Assign(RHS); // Key assignment goes here in derived classes}int FibHeapNode::operator ==(FibHeapNode& RHS){ if (FHN_Cmp(RHS)) return 0; // Key compare goes here in derived classes return 1;}int FibHeapNode::operator <(FibHeapNode& RHS){int X; if ((X=FHN_Cmp(RHS)) != 0) return X < 0 ? 1 : 0; // Key compare goes here in derived classes return 0;}//=========================================================// Print()//=========================================================void FibHeapNode::Print(){ if (NegInfinityFlag) cout << "-inf.";}//***************************************************************************//===========================================================================// FibHeap Constructor//===========================================================================//***************************************************************************FibHeap::FibHeap(){ MinRoot = NULL; NumNodes = NumTrees = NumMarkedNodes = 0; ClearHeapOwnership();}//===========================================================================// FibHeap Destructor//===========================================================================FibHeap::~FibHeap(){FibHeapNode *Temp; if (GetHeapOwnership()) { while (MinRoot != NULL) { Temp = ExtractMin(); delete Temp; } }}//===========================================================================// Insert() - O(1) actual; O(2) amortized//// I am using O(2) here to indicate that although Insert() is// constant time, its amortized rating is more costly because some// of the work of inserting is done by other operations such as// ExtractMin(), which is where tree-balancing occurs.//// The child pointer is deliberately not set to NULL because Insert()// is also used internally to help put whole trees onto the root list.//===========================================================================void FibHeap::Insert(FibHeapNode *NewNode){ if (NewNode == NULL) return;// If the heap is currently empty, then new node becomes singleton// circular root list if (MinRoot == NULL) MinRoot = NewNode->Left = NewNode->Right = NewNode; else {// Pointers from NewNode set to insert between MinRoot and MinRoot->Right NewNode->Right = MinRoot->Right; NewNode->Left = MinRoot;// Set Pointers to NewNode NewNode->Left->Right = NewNode; NewNode->Right->Left = NewNode;// The new node becomes new MinRoot if it is less than current MinRoot if (*NewNode < *MinRoot) MinRoot = NewNode; }// We have one more node in the heap, and it is a tree on the root list NumNodes++; NumTrees++; NewNode->Parent = NULL;}//===========================================================================// Union() - O(1) actual; O(1) amortized//===========================================================================void FibHeap::Union(FibHeap *OtherHeap){FibHeapNode *Min1, *Min2, *Next1, *Next2; if (OtherHeap == NULL || OtherHeap->MinRoot == NULL) return;// We join the two circular lists by cutting each list between its// min node and the node after the min. This code just pulls those// nodes into temporary variables so we don't get lost as changes// are made. Min1 = MinRoot; Min2 = OtherHeap->MinRoot; Next1 = Min1->Right; Next2 = Min2->Right;// To join the two circles, we join the minimum nodes to the next// nodes on the opposite chains. Conceptually, it looks like the way// two bubbles join to form one larger bubble. They meet at one point// of contact, then expand out to make the bigger circle. Min1->Right = Next2; Next2->Left = Min1; Min2->Right = Next1; Next1->Left = Min2;// Choose the new minimum for the heap if (*Min2 < *Min1) MinRoot = Min2;// Set the amortized analysis statistics and size of the new heap NumNodes += OtherHeap->NumNodes; NumMarkedNodes += OtherHeap->NumMarkedNodes; NumTrees += OtherHeap->NumTrees;// Complete the union by setting the other heap to emptiness// then destroying it OtherHeap->MinRoot = NULL; OtherHeap->NumNodes = OtherHeap->NumTrees = OtherHeap->NumMarkedNodes = 0; delete OtherHeap;}//===========================================================================// Minimum - O(1) actual; O(1) amortized//===========================================================================FibHeapNode *FibHeap::Minimum(){ return MinRoot;}//===========================================================================// ExtractMin() - O(n) worst-case actual; O(lg n) amortized//===========================================================================FibHeapNode *FibHeap::ExtractMin(){FibHeapNode *Result;FibHeap *ChildHeap = NULL;// Remove minimum node and set MinRoot to next node if ((Result = Minimum()) == NULL) return NULL; MinRoot = Result->Right; Result->Right->Left = Result->Left; Result->Left->Right = Result->Right; Result->Left = Result->Right = NULL; NumNodes --; if (Result->Mark) { NumMarkedNodes --; Result->Mark = 0; } Result->Degree = 0;// Attach child list of Minimum node to the root list of the heap// If there is no child list, then do no work if (Result->Child == NULL) { if (MinRoot == Result) MinRoot = NULL; }// If MinRoot==Result then there was only one root tree, so the// root list is simply the child list of that node (which is// NULL if this is the last node in the list) else if (MinRoot == Result) MinRoot = Result->Child;// If MinRoot is different, then the child list is pushed into a// new temporary heap, which is then merged by Union() onto the// root list of this heap. else { ChildHeap = new FibHeap(); ChildHeap->MinRoot = Result->Child; }// Complete the disassociation of the Result node from the heap if (Result->Child != NULL) Result->Child->Parent = NULL; Result->Child = Result->Parent = NULL;// If there was a child list, then we now merge it with the// rest of the root list if (ChildHeap) Union(ChildHeap);// Consolidate heap to find new minimum and do reorganize work if (MinRoot != NULL) _Consolidate();// Return the minimum node, which is now disassociated with the heap// It has Left, Right, Parent, Child, Mark and Degree cleared. return Result;}//===========================================================================// DecreaseKey() - O(lg n) actual; O(1) amortized//// The O(lg n) actual cost stems from the fact that the depth, and// therefore the number of ancestor parents, is bounded by O(lg n).//===========================================================================int FibHeap::DecreaseKey(FibHeapNode *theNode, FibHeapNode& NewKey){FibHeapNode *theParent; if (theNode==NULL || *theNode < NewKey) return NOTOK; *theNode = NewKey; theParent = theNode->Parent; if (theParent != NULL && *theNode < *theParent) { _Cut(theNode, theParent); _CascadingCut(theParent); } if (*theNode < *MinRoot) MinRoot = theNode; return OK;}//===========================================================================// Delete() - O(lg n) amortized; ExtractMin() dominates//// Notice that if we don't own the heap nodes, then we clear the// NegInfinityFlag on the deleted node. Presumably, the programmer// will be reusing the node.//===========================================================================int FibHeap::Delete(FibHeapNode *theNode){FibHeapNode Temp;int Result; if (theNode == NULL) return NOTOK; Temp.NegInfinityFlag = 1; Result = DecreaseKey(theNode, Temp); if (Result == OK) if (ExtractMin() == NULL) Result = NOTOK; if (Result == OK) { if (GetHeapOwnership()) delete theNode; else theNode->NegInfinityFlag = 0; } return Result;}//========================================================================// Print()//// Used internally for debugging purposes. The function prints the key// value for each node along the root list, then it calls itself on each// child list. //========================================================================void FibHeap::Print(FibHeapNode *Tree, FibHeapNode *theParent){FibHeapNode* Temp = NULL; if (Tree == NULL) Tree = MinRoot; Temp = Tree; do { if (Temp->Left == NULL) mexPrintf( "(Left is NULL)" ); Temp->Print(); if (Temp->Parent != theParent) mexPrintf("(Parent is incorrect)" ); if (Temp->Right == NULL) mexPrintf( "(Right is NULL)" ); else if (Temp->Right->Left != Temp) mexPrintf( "(Error in left link left) ->" ); else mexPrintf( " <-> " ); Temp = Temp->Right; if (kbhit() && getch() == 27) { cout << "Hit a key to resume or ESC to break\n"; if (getch() == 27) break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -