2017-08-06 246 views
0

我試圖使用遞歸方法實現基於深度優先搜索的兩個函數。我最終試圖將運行時與warshall的算法(我已經工作)進行比較。當我打印我的矩陣時,它會被一對關閉的路徑關閉。遞歸查找圖矩陣DFS中的所有路徑DFS

遞歸是什麼可能會把我扔掉,這是我的弱點。由於頂部if語句if(iIndex1 == iIndex2) return TRUE;,當我嘗試查找是否存在來自(A,A),(B,B),(C,C)等的路徑時,即使沒有路徑,我也將始終獲得1從A到A

typedef enum { FALSE, TRUE } bool; 

/* Recursive function will determine if there is a path from index 1 to 2 
* Based of DFS 
*/ 
bool recPathExists(Graph G, int iIndex1, int iIndex2) 
{ 
    int j; 
    G.nodeArray[iIndex1].visited = TRUE; 
    if(iIndex1 == iIndex2){ 
      return TRUE; 
    } 
    for(j = 0; j < G.iNumNodes; j++){ 
     if(!G.nodeArray[j].visited && G.adjMatrix[iIndex1][j]==1){ 
      if(recPathExists(G, j, iIndex2)) 
       return TRUE; 
     } 
    } 
    return FALSE; 
} 

/* Write a function to find all pairs of nodes which have paths between them. 
* Store this information in the provided pathMatrix. 
*/ 
void allPathsRecFunc(Graph G , int **pathMatrix) 
{ 
    int i, j; 
    for(i = 0; i < G.iNumNodes; i++){ 
     for(j = 0; j < G.iNumNodes; j++){ 
      if(recPathExists(G, i , j)== TRUE){ 
       pathMatrix[i][j] = 1; 
      } 
      resetVisited(G); //resets all nodes to FALSE 
     } 
    } 
} 

它應該是

A 0 1 1 1 1 1 1 1 
B 0 1 0 0 1 1 1 1 
C 0 1 0 0 1 1 1 1 
D 0 0 0 0 0 0 0 0 
E 0 0 0 0 0 0 0 0 
F 0 1 0 0 1 1 1 1 
G 0 1 0 0 1 1 1 1 
H 0 1 0 0 1 1 1 1 

我得到什麼

A 1 1 1 1 1 1 1 1 
B 0 1 0 0 1 1 1 1 
C 0 1 1 0 1 1 1 1 
D 0 0 0 1 0 0 0 0 
E 0 0 0 0 1 0 0 0 
F 0 1 0 0 1 1 1 1 
G 0 1 0 0 1 1 1 1 
H 0 1 0 0 1 1 1 1 
+1

「錯誤的結果」:*錯誤*以哪種方式?順便說一句,儘量保持對'{}'的使用一致(我建議始終使用它們,即使對於單語句循環),並且:如果遞歸是答案,那麼通常像C這樣的絕大多數命令式語言不是選擇工具。 –

+1

@MarcusMüller我通過使用warshall的算法知道最終的矩陣應該是什麼。我使用這個來比較它通過這個方法得到的矩陣結果。該矩陣顯示1的地方應該是0,反之亦然。只有大約一半是準確的。 –

+0

@hnefatl遞歸函數用於確定從iIndex1節點到iIndex2節點的圖形中是否存在路徑,這是基於DFS算法的。需要for循環來檢查所有相鄰節點。我還需要在找到它們時標記訪問的節點。 –

回答

1

您的問題可能在這裏:

for(j = 0; j < G.iNumNodes; j++) 
{ 
    if(!G.nodeArray[j].visited && G.adjMatrix[iIndex1][j] == 1) 
    { 
     return recPathExists(G, j, iIndex2); 
    } 
} 

通過在recPathExists遞歸的結果,你沒有檢查循環中可能到達的其他可能節點(本質上,你是過早返回失敗,並錯過可能的路徑)。

我相信你想一點點修改:

for(j = 0; j < G.iNumNodes; j++) 
{ 
    if(!G.nodeArray[j].visited && G.adjMatrix[iIndex1][j] == 1) 
    { 
     if (recPathExists(G, j, iIndex2)) 
      return TRUE; 
    } 
} 

也就是說,「如果一個路徑確實存在,作爲回報我們發現它如果沒有,繼續找。」

+0

好吧,似乎已經奏效。我留下的唯一問題是,當我有(A,A)(B,B)(C,C)等的時候,if(iIndex1 == iIndex2)頂部的if語句總是爲1即使(A,A)沒有路徑。我努力想知道我可以添加到if語句中以避免這種情況。 –

+0

@below_avg_st最簡單的方法可能是創建一個調用你現有函數的包裝函數。在你的包裝器中,檢查'iIndex1 == iIndex2',然後是'G.adjMatrix [iIndex1] [iIndex2] == 1'(有一個循環)。如果沒有,請致電您現有的功能。一般來說,如果您在開始時有特殊情況,只需在開始之前添加一個步驟即可處理它。 – hnefatl

-1

我的深度優先搜索使用遞歸,但它輸出父陣列,雖然功能應該是的AME。它有一個完美的成績,所以我知道它的工作原理。希望能幫助到你。

https://github.com/grantSwalwell/Data-Structures/blob/master/Depth%20First%20Search.h

算法〜

  1. 布爾陣列,參觀了萎靡不振的節點
  2. 搜索數陣列來衡量訪問深度
  3. 深度遞增,並拿出搜索NUM
  4. 撥打0.0上的DFS
  5. 對於每個未訪問鄰居
  6. DFS深度+ 1,搜索=深度,走訪=真
  7. 回報父母陣列,顯示搜索模式

    // Depth First Search recursive helper method 
    
    
    void DFS(Graph& G, int v0, Array<bool>* visited, Array<int>* search, int 
    depth) 
    { 
    
        // set visited 
        (*visited)[v0] = true; 
    
        // set search num 
        (*search)[v0] = depth; 
    
        // iterate through neighbors 
        for (int i = 0; i < G.nodes(); i++) 
        { 
         // if i is a neighbor 
         if (G.edge(i, v0)) 
         { 
          // if it has not been visited 
          if (!(*visited)[i]) 
          { 
           // call DFS 
           DFS(G, i, visited, search, depth + 1); 
          } 
         } // end if 
        } // end for 
    } 
    
    // Depth First Search 
    Array<int>* DFS(Graph& G, int v0) 
    { 
    
        // visited array 
        Array<bool>* visited = new Array<bool>(G.nodes()); 
    
        // search number array, order of visitation 
        Array<int>* search = new Array<int>(G.nodes()); 
    
        // initialize both arrays 
        for (int i = 0; i < G.nodes(); i++) 
        { 
         (*visited)[i] = false; 
         (*search)[i] = 1; 
        } 
    
        // create depth field 
        int depth = 1; 
    
        // call DFS 
        DFS(G, v0, visited, search, depth); 
    
        return search; 
    
    }; 
    
+0

請參閱[這裏](https://meta.stackexchange.com/questions/8231/are-answers-that-just-contain-links-elsewhere-really-good-answers)瞭解爲什麼答案的理由清單包含鏈接不一定是很好的答案。也許更新您的答案,包括鏈接中的相關代碼片段,以及解釋差異是什麼以及它爲什麼起作用。 – hnefatl