⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dijkstra.cpp

📁 实现核ISOMAP算法,解决测试点问题和ROBUST问题
💻 CPP
📖 第 1 页 / 共 2 页
字号:
        }
     } while (Temp != NULL && Temp != Tree);
     mexPrintf( "\n" );

     Temp = Tree;
     do {
	mexPrintf( "Children of " );
	Temp->Print();
	mexPrintf( ": " );
	if (Temp->Child == NULL)
	     mexPrintf( "NONE\n" );
        else Print(Temp->Child, Temp);
	Temp = Temp->Right;
     } while (Temp!=NULL && Temp != Tree);

     if (theParent == NULL)
     {
     char ch;

	 mexPrintf( "\n\n\n" );
         cin >> ch;
     }
}

//===========================================================================
//===========================================================================

void FibHeap::_Exchange(FibHeapNode*& N1, FibHeapNode*& N2)
{
FibHeapNode *Temp;

     Temp = N1;
     N1 = N2;
     N2 = Temp;
}

//===========================================================================
// Consolidate()
//
// Internal function that reorganizes heap as part of an ExtractMin().
// We must find new minimum in heap, which could be anywhere along the
// root list.  The search could be O(n) since all nodes could be on
// the root list.  So, we reorganize the tree into more of a binomial forest
// structure, and then find the new minimum on the consolidated O(lg n) sized
// root list, and in the process set each Parent pointer to NULL, and count
// the number of resulting subtrees.
//
// Note that after a list of n inserts, there will be n nodes on the root
// list, so the first ExtractMin() will be O(n) regardless of whether or
// not we consolidate.  However, the consolidation causes subsequent
// ExtractMin() operations to be O(lg n).  Furthermore, the extra cost of
// the first ExtractMin() is covered by the higher amortized cost of
// Insert(), which is the real governing factor in how costly the first
// ExtractMin() will be.
//===========================================================================

void FibHeap::_Consolidate()
{
FibHeapNode *x, *y, *w;
FibHeapNode *A[1+8*sizeof(long)]; // 1+lg(n)
int  I=0, Dn = 1+8*sizeof(long);
short d;

// Initialize the consolidation detection array

     for (I=0; I < Dn; I++)
          A[I] = NULL;

// We need to loop through all elements on root list.
// When a collision of degree is found, the two trees
// are consolidated in favor of the one with the lesser
// element key value.  We first need to break the circle
// so that we can have a stopping condition (we can't go
// around until we reach the tree we started with
// because all root trees are subject to becoming a
// child during the consolidation).

     MinRoot->Left->Right = NULL;
     MinRoot->Left = NULL;
     w = MinRoot;

     do {
//cout << "Top of Consolidate's loop\n";
//Print(w);

	x = w;
        d = x->Degree;
        w = w->Right;

// We need another loop here because the consolidated result
// may collide with another large tree on the root list.

        while (A[d] != NULL)
        {
             y = A[d];
	     if (*y < *x)
		 _Exchange(x, y);
             if (w == y) w = y->Right;
             _Link(y, x);
             A[d] = NULL;
             d++;
//cout << "After a round of Linking\n";
//Print(x);
	}
	A[d] = x;

     } while (w != NULL);

// Now we rebuild the root list, find the new minimum,
// set all root list nodes' parent pointers to NULL and
// count the number of subtrees.

     MinRoot = NULL;
     NumTrees = 0;
     for (I = 0; I < Dn; I++)
          if (A[I] != NULL)
              _AddToRootList(A[I]);
}

//===========================================================================
// The node y is removed from the root list and becomes a subtree of node x.
//===========================================================================

void FibHeap::_Link(FibHeapNode *y, FibHeapNode *x)
{
// Remove node y from root list

     if (y->Right != NULL)
	 y->Right->Left = y->Left;
     if (y->Left != NULL)
         y->Left->Right = y->Right;
     NumTrees--;

// Make node y a singleton circular list with a parent of x

     y->Left = y->Right = y;
     y->Parent = x;

// If node x has no children, then list y is its new child list

     if (x->Child == NULL)
	 x->Child = y;

// Otherwise, node y must be added to node x's child list

     else
     {
         y->Left = x->Child;
         y->Right = x->Child->Right;
         x->Child->Right = y;
         y->Right->Left = y;
     }

// Increase the degree of node x because it's now a bigger tree

     x->Degree ++;

// Node y has just been made a child, so clear its mark

     if (y->Mark) NumMarkedNodes--;
     y->Mark = 0;
}

//===========================================================================
//===========================================================================

void FibHeap::_AddToRootList(FibHeapNode *x)
{
     if (x->Mark) NumMarkedNodes --;
     x->Mark = 0;

     NumNodes--;
     Insert(x);
}

//===========================================================================
// Remove node x from the child list of its parent node y
//===========================================================================

void FibHeap::_Cut(FibHeapNode *x, FibHeapNode *y)
{
     if (y->Child == x)
         y->Child = x->Right;
     if (y->Child == x)
	 y->Child = NULL;

     y->Degree --;

     x->Left->Right = x->Right;
     x->Right->Left = x->Left;

     _AddToRootList(x);
}

//===========================================================================
// Cuts each node in parent list, putting successive ancestor nodes on the
// root list until we either arrive at the root list or until we find an
// ancestor that is unmarked.  When a mark is set (which only happens during
// a cascading cut), it means that one child subtree has been lost; if a
// second subtree is lost later during another cascading cut, then we move
// the node to the root list so that it can be re-balanced on the next
// consolidate. 
//===========================================================================

void FibHeap::_CascadingCut(FibHeapNode *y)
{
FibHeapNode *z = y->Parent;

     while (z != NULL)
     {
         if (y->Mark == 0)
         {
             y->Mark = 1;
             NumMarkedNodes++;
             z = NULL;
         }
         else
         {
             _Cut(y, z);
             y = z;
	     z = y->Parent;
         }
     }
}


class HeapNode : public FibHeapNode
{
      double   N;
      long int IndexV;

public:

      HeapNode() : FibHeapNode() { N = 0; };   

      virtual void operator =(FibHeapNode& RHS);
      virtual int  operator ==(FibHeapNode& RHS);
      virtual int  operator <(FibHeapNode& RHS);

      virtual void operator =(double NewKeyVal );
      virtual void Print();

      double GetKeyValue() { return N; };       /* !!!! */
      void SetKeyValue(double n) { N = n; };

      long int GetIndexValue() { return IndexV; };
      void SetIndexValue( long int v) { IndexV = v; };

};

void HeapNode::Print()
{
     FibHeapNode::Print();
     mexPrintf( "%f (%d)" , N , IndexV );
}

void HeapNode::operator =(double NewKeyVal)
{
     HeapNode Temp;
     Temp.N = N = NewKeyVal;
     FHN_Assign(Temp);
}

void HeapNode::operator =(FibHeapNode& RHS)
{
     FHN_Assign(RHS);
     N = ((HeapNode&) RHS).N;
}

int  HeapNode::operator ==(FibHeapNode& RHS)
{
     if (FHN_Cmp(RHS)) return 0;
     return N == ((HeapNode&) RHS).N ? 1 : 0;
}

int  HeapNode::operator <(FibHeapNode& RHS)
{
int X;

     if ((X=FHN_Cmp(RHS)) != 0)
	  return X < 0 ? 1 : 0;

     return N < ((HeapNode&) RHS).N ? 1 : 0;
};

int IntCmp(const void *pA, const void *pB)
{
int A, B;

    A = *((const int *) pA);
    B = *((const int *) pB);
    if (A < B) return -1;
    if (A == B) return 0;
    return 1; 
}

void dodijk_sparse( 
             long int M,
             long int N,
             long int S,
             double   *D,
             double   *sr,
             int      *irs,
             int      *jcs,
             HeapNode *A,
             FibHeap  *theHeap  )
{
   int      finished;
   long int i,startind,endind,whichneighbor,ndone,index,switchwith,closest,closesti;
   long int *INDICES;
   double   closestD,arclength; 
   double   INF,SMALL,olddist;
   HeapNode *Min;
   HeapNode Temp;

   INF   = mxGetInf();
   SMALL = mxGetEps();

   /* initialize */
   for (i=0; i<M; i++) 
   {
      if (i!=S) A[ i ] = (double) INF; else A[ i ] = (double) SMALL;
      if (i!=S) D[ i ] = (double) INF; else D[ i ] = (double) SMALL;
	  theHeap->Insert( &A[i] );
      A[ i ].SetIndexValue( (long int) i );
   }
   

   // Insert 0 then extract it.  This will cause the
   // Fibonacci heap to get balanced.

   theHeap->Insert(&Temp);
   theHeap->ExtractMin();

   /*theHeap->Print();
   for (i=0; i<M; i++)
   {
      closest = A[ i ].GetIndexValue();
      closestD = A[ i ].GetKeyValue();
      mexPrintf( "Index at i=%d =%d  value=%f\n" , i , closest , closestD );
   }*/   

   /* loop over nonreached nodes */
   finished = 0;
   ndone    = 0;
   while ((finished==0) && (ndone < M))
   {
      //if ((ndone % 100) == 0) mexPrintf( "Done with node %d\n" , ndone );

      Min = (HeapNode *) theHeap->ExtractMin();
      closest  = Min->GetIndexValue();
      closestD = Min->GetKeyValue();

      if ((closest<0) || (closest>=M)) mexErrMsgTxt( "Minimum Index out of bound..." );

      //theHeap->Print();
      //mexPrintf( "EXTRACTED MINIMUM  NDone=%d S=%d closest=%d closestD=%f\n" , ndone , S , closest , closestD );
      //mexErrMsgTxt( "Exiting..." );

      D[ closest ] = closestD;

      if (closestD == INF) finished=1; else
      {
         /* add the closest to the determined list */
         ndone++;         
          
         /* relax all nodes adjacent to closest */
         startind = jcs[ closest   ];
         endind   = jcs[ closest+1 ] - 1;

         if (startind!=endind+1)
         for (i=startind; i<=endind; i++)
         {
            whichneighbor = irs[ i ];
            arclength = sr[ i ];
            olddist   = D[ whichneighbor ];

            //mexPrintf( "INSPECT NEIGHBOR #%d  olddist=%f newdist=%f\n" , whichneighbor , olddist , closestD+arclength );            

            if ( olddist > ( closestD + arclength ))
            {
               D[ whichneighbor ] = closestD + arclength;

	           Temp = A[ whichneighbor ];
	           Temp.SetKeyValue( closestD + arclength );
               theHeap->DecreaseKey( &A[ whichneighbor ], Temp );

               //mexPrintf( "UPDATING NODE #%d  olddist=%f newdist=%f\n" , whichneighbor , olddist , closestD+arclength );
            }
         }

      }
      
   }
}


void mexFunction(
		 int          nlhs,
		 mxArray      *plhs[],
		 int          nrhs,
		 const mxArray *prhs[]
		 )
{
  double    *sr,*D,*P,*SS,*Dsmall,*Psmall;
  int       *irs,*jcs;
  long int  M,N,S,MS,NS,i,j,in;

  HeapNode *A = NULL;
  FibHeap  *theHeap = NULL;
  
  if (nrhs != 2)
  {
      mexErrMsgTxt( "Only 2 input arguments allowed." );
  }
      else if (nlhs != 1) 
   {
      mexErrMsgTxt( "Only 1 output argument allowed." );
   }
   
   M = mxGetM( prhs[0] );
   N = mxGetN( prhs[0] );
   
   if (M != N) mexErrMsgTxt( "Input matrix needs to be square." );
    
   SS = mxGetPr(prhs[1]);
   MS = mxGetM( prhs[1] );
   NS = mxGetN( prhs[1] );
     
   if ((MS==0) || (NS==0) || ((MS>1) && (NS>1))) mexErrMsgTxt( "Source nodes are specified in one dimensional matrix only" );
   if (NS>MS) MS=NS;
     
   plhs[0] = mxCreateDoubleMatrix( MS,M, mxREAL);
   D = mxGetPr(plhs[0]);
    
   Dsmall = (double *) mxCalloc( M , sizeof( double ));

   if (mxIsSparse( prhs[ 0 ] ) == 1)
   {
     /* dealing with sparse array */
     sr      = mxGetPr(prhs[0]);
     irs     = mxGetIr(prhs[0]);
     jcs     = mxGetJc(prhs[0]);

     // Setup for the Fibonacci heap

     

     for (i=0; i<MS; i++)
     {
        if ((theHeap = new FibHeap) == NULL || (A = new HeapNode[M+1]) == NULL )
        {
	      mexErrMsgTxt( "Memory allocation failed-- ABORTING.\n" );
        }

        theHeap->ClearHeapOwnership();

        S = (long int) *( SS + i );
        S--;

        if ((S < 0) || (S > M-1)) mexErrMsgTxt( "Source node(s) out of bound" );

        /* -------------------------------------------------------------------------------------------------
                                    run the dijkstra code 
           ------------------------------------------------------------------------------------------------- */

        //mexPrintf( "Working on i=%d\n" , i );

        dodijk_sparse( M,N,S,Dsmall,sr,irs,jcs,A,theHeap );

        for (j=0; j<M; j++) 
        {
           *( D + j*MS + i ) = *( Dsmall + j );

         //mexPrintf( "Distance i=%d to j=%d =%f\n" , S+1 , j , *( Dsmall + j ) ); 
        }
         
        
       
        /* -------------------------------------------------------------------------------------------------
                                    end of the dijkstra code 
           ------------------------------------------------------------------------------------------------- */
        
        delete theHeap;
        delete[] A;
     } 

     

   } else mexErrMsgTxt( "Function not implemented for full arrays" );

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -