AOE 关键路径求解

来源:互联网 发布:生物医学数据挖掘 编辑:程序博客网 时间:2024/05/29 02:32
// 求解关键路径

// 效率极低 最好使用 矩阵 或者十字链表

// 若采用十字链表和矩阵可以大幅度的提高效率

#include "stdafx.h"
#include <iostream>
#include <vector>
#include <list>
#include <algorithm>

enum
{
      Vertex_No_Connection       = -1,
      Vertex_Total_Number       = 9,
      Vertex_Max_Edge_Value      = 10000,
};

// 连接头结点的后面 next 结点
struct SNextHeadNode
{
      int nVertexNode ;
      int nEdgeValue ;

      SNextHeadNode* pNextNode ;
};

// 头结点
struct SHeadNode
{
      int             nVertexNode;
      SNextHeadNode pFirstLink ;
};

SHeadNode * headNodeSet[ Vertex_Total_Number];

int InDgreeOfNodeSet[ Vertex_Total_Number];
int nPreOrderTag[ Vertex_Total_Number];   // 前向遍历产生的 Tag 标识
int nPostOrderTag[ Vertex_Total_Number];  // 后向遍历产生的 Tag 标识
int nSourceIndex;                        // 源点
int nMaxNodeIndex;                       // 汇点

void InitHeadList()
{
      int nThreeItemNum [11][3] =
     {
          { 0, 1, 6 }, { 0, 2, 4 }, { 0, 3, 5 }, { 1, 4, 1 },
          { 2, 4, 1 }, { 4, 6, 9 }, { 4, 7, 7 }, { 6, 8, 2 },
          { 7, 8, 4 }, { 3, 5, 2 }, { 5, 7, 4 }
     };

      for( int i = 0; i < Vertex_Total_Number ; ++i )
     {
           headNodeSet[i ] = new SHeadNode;
           if( !headNodeSet [i] )
          {
               std::cout <<"Error 1"<< std::endl ;
               system( "pause" );
               return ;
          }

           headNodeSet[i ]->nVertexNode = i;
           headNodeSet[i ]->pFirstLink  = NULL;
     }

      for( int i = 0; i < 11; ++i )
     {
           SNextHeadNode* pNextHeadNode = new SNextHeadNode ;
           if( !pNextHeadNode )
          {
               std::cout <<"Error 2"<< std::endl ;
               system( "pause" );
               return ;
          }

           pNextHeadNode->pNextNode     = NULL;
           pNextHeadNode->nVertexNode   = nThreeItemNum [i][1];
           pNextHeadNode->nEdgeValue    = nThreeItemNum [i][2];

           // Front Insert
           int nSourceIndex = nThreeItemNum[ i][0];
           pNextHeadNode->pNextNode                = headNodeSet [nSourceIndex]-> pFirstLink;
           headNodeSet[nSourceIndex ]->pFirstLink  = pNextHeadNode ;
     }
}

void InitInDgreeOfNodeSet()
{
      for( int i = 0; i < Vertex_Total_Number ; ++i )
     {
           InDgreeOfNodeSet[i ] = 0;
     }

      for( int i = 0; i < Vertex_Total_Number ; ++i )
     {
           SNextHeadNode* pLinkHeadNode = headNodeSet [i]-> pFirstLink;
           while( pLinkHeadNode )
          {
               int nLinkNode = pLinkHeadNode-> nVertexNode;
              ++ InDgreeOfNodeSet[nLinkNode ];
               pLinkHeadNode = pLinkHeadNode ->pNextNode;
          }
     }
}

void InitPreOrderTag()
{
      // nPreOrderTag
      for( int i = 0; i < Vertex_Total_Number ; ++i )
           nPreOrderTag[i ] = 0;
}

void FindTheSourceIndex()
{
      for( int i = 0; i < Vertex_Total_Number ; ++i )
     {
           if( InDgreeOfNodeSet [i] == 0 )
          {
               nSourceIndex = i ;
               break;
          }
     }
}

void SolutionPostNode( int nMaxValue , int nMaxIndex )
{
      if( nMaxIndex == nSourceIndex )
           return ;

      for( int i = 0; i < Vertex_Total_Number ; ++i )
     {
           int nSourceNodeIndex      = headNodeSet [i]-> nVertexNode;
           SNextHeadNode* pLinkNode = headNodeSet [i]-> pFirstLink;
           while( pLinkNode )
          {
               int nDestNodeIndex = pLinkNode ->nVertexNode;
               if( nDestNodeIndex == nMaxIndex )
              {
                    int nEdgeValue = pLinkNode ->nEdgeValue;

                    if( nMaxValue - nEdgeValue < nPostOrderTag [nDestNodeIndex] )
                   {    
                         nPostOrderTag[nSourceNodeIndex ] = nMaxValue - nEdgeValue;
                         SolutionPostNode( nPostOrderTag [nSourceNodeIndex], nSourceNodeIndex );
                   }
              }

               pLinkNode = pLinkNode ->pNextNode;
          }
     }
}

void Process()
{
      FindTheSourceIndex();

      // 寻找入度为的结点找到最长路径,即最短时间
      while( 1 )
     {
           int nIndex = -1;
           for( int i = 0; i < Vertex_Total_Number ; ++i )
          {
               if( InDgreeOfNodeSet [i] == 0 )
              {
                    nIndex = i ;
                    break;
              }
          }

           if( nIndex == -1 )
               break;

           // 找到度数为点将其入度置为 -1
           InDgreeOfNodeSet[nIndex ] = -1;
          
           SNextHeadNode* pLinkNextNode = headNodeSet [nIndex]-> pFirstLink;
           while( pLinkNextNode )
          {
               int nNodeIndex = pLinkNextNode ->nVertexNode;
               int nEdgeValue = pLinkNextNode-> nEdgeValue;
              
              -- InDgreeOfNodeSet[nNodeIndex ];
              
               if( nPreOrderTag [nIndex] + nEdgeValue > nPreOrderTag [nNodeIndex] )
                    nPreOrderTag[nNodeIndex ] = nPreOrderTag [nIndex] + nEdgeValue;

               pLinkNextNode = pLinkNextNode ->pNextNode;
          }
     }

     
      // 求解nPost 后向结点的值
      int nMaxValue = -1;
      for( int i = 0; i < Vertex_Total_Number ; ++i )
     {
           if( nPreOrderTag [i] > nMaxValue )
          {
               nMaxValue      = nPreOrderTag[ i];
               nMaxNodeIndex  = i ;
          }
     }

      for( int i = 0; i < Vertex_Total_Number ; ++i )
     {
           nPostOrderTag[i ] = nMaxValue;
     }

      SolutionPostNode( nMaxValue , nMaxNodeIndex );
      nPostOrderTag[nSourceIndex ] = 0;

}

void PrintHelp( int nSource )
{
      if( nSource == nMaxNodeIndex )
     {
           std::cout <<nSource<< std::endl ;
           return ;
     }

      std::cout <<nSource<< "---->" ;
     
      SNextHeadNode* pLinkNextHead = headNodeSet [nSource]-> pFirstLink;
      while( pLinkNextHead )
     {
           int nVertexIndex = pLinkNextHead-> nVertexNode;
           if( nPostOrderTag [nVertexIndex] == nPreOrderTag [nVertexIndex] )
          {
               PrintHelp( nVertexIndex );
          }

           pLinkNextHead = pLinkNextHead ->pNextNode;
     }
}

void PrintPathInfo()
{
      // 广度搜索。。。输出所有的最优解
      PrintHelp( nSourceIndex );
}


int _tmain( int argc , _TCHAR* argv[])
{
      InitHeadList();
      InitInDgreeOfNodeSet ();
      InitPreOrderTag();
      Process();
      PrintPathInfo();
     
      system("pause" );
      return 0;
}
  

0 0
原创粉丝点击