图的更多相关算法-4(拓扑排序)

  
  
  
  
  1. int TopSort(AGraph *ag, int topsq[])        //此算法是利用堆栈来进行拓扑排序 
  2. {    
  3.     int loop1 = 0,     node = 0, ivar  = ag->n, count = 0; 
  4.     int stack[MAXSIZE],top = -1; 
  5.     ArcNode *temp = NULL; 
  6.  
  7.     for(loop1 = 0; loop1 < ivar; ++loop1)           //此循环找到入度为0的点,并把其入栈 
  8.     { 
  9.         if(ag->adjlist[loop1].indegres == 0) 
  10.         { 
  11.             ++top; 
  12.             stack[top] = loop1; 
  13.         } 
  14.     } 
  15.  
  16.     while(top > -1) 
  17.     { 
  18.         node = stack[top]; 
  19.         --top;                      cout<<"out stack "<<node<<endl; 
  20.         topsq[count] = node;                //此处出栈一个入度为0的点,并把其相邻的节点的入度--, 
  21.         ++count; 
  22.         temp = NULL; 
  23.         temp = ag->adjlist[node].firstarc; 
  24.         while(temp != NULL) 
  25.         { 
  26.             --ag->adjlist[temp->adjvex].indegres; 
  27.             if(ag->adjlist[temp->adjvex].indegres == 0)         //如果--其相邻的入度后使其入度为0则把它入栈 
  28.             { 
  29.                 ++top; 
  30.                 stack[top] = temp->adjvex; 
  31.             } 
  32.             temp = temp->nextarc;            
  33.         } 
  34.     } 
  35.     if(count < ag->n)                                           //count记录了总共有多少个节点符合条件,如果节点数目不与count相同的话,就说明有回路 
  36.     {cout<<"find circle"<<endl; return 0;} 
  37.     else { cout<<"no circle"<<endl; return 1; } 
  38.  
  39. int TopSort2(AGraph *ag, int topsq[])                           //此算法是利用队列取代堆栈 
  40.     int queue[MAXSIZE], front = -1, rear = -1; 
  41.     int ivar = ag->n, loop1 = 0, count = 0, node = 0; 
  42.     ArcNode *temp = NULL; 
  43.  
  44.     for(loop1 = 0; loop1 < ivar; ++loop1) 
  45.     { 
  46.         if(ag->adjlist[loop1].indegres == 0) 
  47.         { 
  48.             ++rear; 
  49.             queue[rear] = loop1; 
  50.         } 
  51.     } 
  52.  
  53.     while(rear > front) 
  54.     { 
  55.         ++front; 
  56.         node = queue[front]; 
  57.         topsq[count] = node; 
  58.         ++count; 
  59.         cout<<"out stack "<<node<<endl; 
  60.         temp = NULL; 
  61.         temp = ag->adjlist[node].firstarc; 
  62.         while(temp != NULL) 
  63.         { 
  64.             --ag->adjlist[temp->adjvex].indegres; 
  65.             if(ag->adjlist[temp->adjvex].indegres == 0) 
  66.             { 
  67.                 ++rear; 
  68.                 queue[rear] = temp->adjvex; 
  69.             } 
  70.             temp = temp->nextarc; 
  71.         } 
  72.     } 
  73.     if(count < ag->n) 
  74.     {cout<<"find circle"<<endl; return 0;} 
  75.     else { cout<<"no circle"<<endl; return 1; } 
  76.  
  77. /* 
  78.     判断一个图是否存在回路: 
  79.     1. 利用拓扑排序 
  80.     2. 如图g是有n个节点的无向图,若g的边数e>=n,则一定有回路 
  81.     3. 如图是n个节点的无向连通图,如g的每个顶点的度>=2,则图g有回路存在 
  82.     4. 利用深度优先遍历可以判断g中是否存在回路 
  83.         对于无向图,如遍历的过程中遇到了回边则必定存在环 
  84.         对于有向图,这条回边可能是指向深度优先森林中的另一颗生成树上的顶点的弧,但是如果从有向图上的某个顶点v出发 
  85.         进行深度优先遍历,若在从此节点的深度优先遍历结束之前出现了一条回边,则图中一定包含环。 因此需要明确从这个顶点的深度遍历是否完成 
  86. */ 
  87.  
  88. int visited2 [MAXSIZE];           //visited2[i]  == 0 表示对 i 未被访问过,否则已经访问过 
  89. int finished [MAXSIZE];            //finished[i] == 0 表示对顶点 i 的遍历未结束,否则已经结束 
  90. int flag = 1;                     //flag == 1 表示AOV网中没有环,为0 表示有环 
  91. typedef struct node 
  92.     int data; 
  93.     struct node *next; 
  94. }NodeType; 
  95.  
  96. NodeType *head = NULL, *temp = NULL; 
  97. void dfs(AGraph *ag, int begin)         //此算法是对有向图进行深度优先遍历 
  98.     ArcNode  *arctemp  = NULL; 
  99.     NodeType *nodetemp = NULL; 
  100.     visited2[begin]     = 1; 
  101.     finished[begin]    = 0;             //此处赋值为0 表示对begin的节点刚开始遍历,还有访问完成 
  102.      
  103.     arctemp = ag->adjlist[begin].firstarc; 
  104.     while(arctemp != NULL) 
  105.     { 
  106.         if(visited2[arctemp->adjvex] == 1 && finished[arctemp->adjvex] == 0)    //此判断表示遇到的节点已经访问过,并且没有访问完成,则说明遇到了回路 
  107.         { flag = 0;}                                //如果finished[i] == 1 则表示对i节点的遍历已经完成此时若是遇到i节点,则表示是图中的森林 
  108.         if(visited2[arctemp->adjvex] == 0)                                  //没有访问过,深度访问 
  109.         {  dfs(ag, arctemp->adjvex);   finished[arctemp->adjvex] = 1; }     //finished[i] == 1,表示对节点i一经访问完成, 因此设置使finished[i] == 1,应该再dfs遍历节点i之后 
  110.         arctemp = arctemp->nextarc; 
  111.     } 
  112.     //此时应该注意到下面的代码在递归的回溯过程才会执行,因此链表保存的是逆向拓扑排序的顺序节点 
  113.     nodetemp = (NodeType *)malloc(sizeof(NodeType)); 
  114.     nodetemp->data = begin; 
  115.     nodetemp->next = NULL; 
  116.     if(head == NULL) 
  117.     { 
  118.         head       = nodetemp; 
  119.         temp       = nodetemp; 
  120.         temp->next = NULL; 
  121.     }else 
  122.     {        
  123.         temp->next     = nodetemp; 
  124.         temp           = nodetemp; 
  125.     } 
  126.  
  127. void dfs_topsort(AGraph *ag) 
  128.     int loop1 = 0, ivar = ag->n; 
  129.  
  130.     for(loop1 = 0; loop1 < MAXSIZE; ++loop1) 
  131.     { 
  132.         visited2[loop1]  = 0; 
  133.         finished[loop1] = 0; 
  134.     } 
  135.      
  136.     loop1 = 0; 
  137.     while(flag == 1 && loop1 < ivar)            //此处为什么要进行循环 dfs 遍历, 因为一个有向无环图中,它的入度为0的点可能不止有一个, 也就是相当于遍历森林 
  138.     { 
  139.         if(visited2[loop1] == 0) 
  140.         { 
  141.             dfs(ag,loop1);                      //此函数中当出现环的时候把flag置为0 
  142.             finished[loop1] = 1; 
  143.         } 
  144.         ++loop1; 
  145.     } 
  146.     if(flag == 1)                              //flag 标志表示图中没有环出项 
  147.     { 
  148.         cout<<"逆序为:"<<endl; 
  149.         temp = head; 
  150.         while(temp != NULL) 
  151.         { 
  152.             cout<<temp->data<<' '
  153.             temp = temp->next; 
  154.         } 
  155.         cout<<endl; 
  156.     }else { cout<<"circle is found"<<endl; } 
  157.  
  158.  
  159.  
  160. typedef struct line 
  161.     int begin, end; 
  162.     int weight; 
  163. }LineType; 
  164.  
  165. void MakeLine(AGraph *ag, LineType lines[]) 
  166.     int loop1 = 0, linenum = 0; 
  167.     ArcNode *temp = NULL; 
  168.  
  169.     for(loop1 = 0; loop1 < ag->n; ++loop1) 
  170.     { 
  171.         temp = ag->adjlist[loop1].firstarc; 
  172.         while(temp != NULL) 
  173.         { 
  174.             lines[linenum].begin  = loop1; 
  175.             lines[linenum].end    = temp->adjvex; 
  176.             lines[linenum].weight = temp->weight; 
  177.  
  178.             temp                  = temp->nextarc; 
  179.             ++linenum; 
  180.         } 
  181.     } 
  182.  
  183. int CriticalPath(AGraph *ag) 
  184.     int ivar = 0, loop1 = 0; 
  185.     int topsq[MAXSIZE], ve[MAXSIZE], vl[MAXSIZE], e[MAXSIZE], l[MAXSIZE]; 
  186.     ArcNode *temp = NULL; 
  187.     LineType lines[MAXSIZE]; 
  188.  
  189.     ivar = TopSort(ag,topsq); 
  190.     if(ivar == 0)  
  191.     { cout<<"this graph has a circle"<<endl; return 0;} 
  192.          
  193.     ivar = ag->n; 
  194.     for(loop1 = 0; loop1 < MAXSIZE; ++loop1) 
  195.     { 
  196.         ve[loop1] = 0;    e[loop1] = 0; 
  197.         vl[loop1] = 1000; l[loop1] = 0; 
  198.     } 
  199.  
  200.     MakeLine(ag, lines); 
  201.      
  202.     for(loop1 = 0; loop1 < ivar; ++loop1) 
  203.     { 
  204.         temp = ag->adjlist[loop1].firstarc; 
  205.         while(temp != NULL) 
  206.         { 
  207.             if(ve[temp->adjvex] < ( temp->weight + ve[loop1] )) 
  208.                 ve[temp->adjvex] = temp->weight + ve[loop1]; 
  209.             temp = temp->nextarc; 
  210.         } 
  211.     } 
  212.          
  213. /* 
  214.     for(loop1 = 0; loop1 < ivar; ++loop1)    
  215.         cout<<ve[loop1]<<' ';    
  216.     cout<<endl; 
  217. */ 
  218.  
  219. //  cout<<ivar<<endl; 
  220.     vl[ivar - 1] = ve[ivar - 1]; 
  221.     for(loop1 = ivar - 1; loop1 >= 0; --loop1) 
  222.     { 
  223.         temp = ag->adjlist[loop1].firstarc; 
  224.         while(temp != NULL) 
  225.         { 
  226.             if((vl[temp->adjvex] - temp->weight )< vl[loop1]) 
  227.                 vl[loop1] = vl[temp->adjvex] - temp->weight; 
  228.             temp = temp->nextarc; 
  229.         } 
  230.     } 
  231. /* 
  232.     for(loop1 = 0; loop1 < ivar; ++loop1)    
  233.         cout<<vl[loop1]<<' ';    
  234.     cout<<endl; 
  235. */ 
  236.  
  237.     for(loop1 = 0; loop1 < ag->e; ++loop1)   
  238.     { 
  239.         cout<<loop1 <<" line from node  "<<lines[loop1].begin<<" to node "<<lines[loop1].end<<" weight is "<<lines[loop1].weight<<endl; 
  240.     } 
  241.     for(loop1 = 0; loop1 < ag->e; ++loop1)   
  242.     {   e[loop1] = ve[lines[loop1].begin];   
  243.         l[loop1] = vl[lines[loop1].end] - lines[loop1].weight; 
  244.         cout<<"from node "<<lines[loop1].begin<<" to node "<<lines[loop1].end<<" e is "<<e[loop1]<<"  l is "<<l[loop1]<<endl; 
  245.     } 
  246.  
  247.     for(loop1 = 0; loop1 < ag->e; ++loop1)   
  248.         if(e[loop1] == l[loop1]) 
  249.             cout<<loop1<<' '
  250.  
  251.     cout<<endl; 
  252.  
  253.     return 1; 

 

你可能感兴趣的:(算法,图,拓扑排序)