首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

C 語言遞歸回形取數死循環:賦值誤寫、終止條件缺失與邏輯重構

     編輯:程式設計疑難解答

代碼核心缺陷

  1. 賦值寫成比較:b[i][j]==1; 應為 b[i][j]=1;,導致訪問標記永不生效,重複訪問同一單元格。
  2. 遞歸終止條件位置錯誤:if(num==m*n) return; 放在遞歸調用之後,且所有方向判斷均為獨立 if 而非 else if,導致返回後繼續執行後續 if 進入下一層遞歸。
  3. 方向轉換邏輯混亂:s++ 後未重新驗證邊界,直接遞歸調用新坐標,極易越界或陷入無限轉向。

修正版核心邏輯


void solve(int i, int j) {
    // 1. 邊界與訪問檢查
    if (i < 0 || i >= m || j < 0 || j >= n || b[i][j]) return;
    
    // 2. 訪問當前單元格
    printf("%d ", a[i][j]);
    b[i][j] = 1;           // 修正:賦值
    if (++num == m * n) return; // 修正:前置遞增並檢查終止
    
    // 3. 嘗試按當前方向前進
    int ni = i, nj = j;
    switch (s % 4) {
        case 0: ni = i + 1; break; // 向下
        case 1: nj = j + 1; break; // 向右
        case 2: ni = i - 1; break; // 向上
        case 3: nj = j - 1; break; // 向左
    }
    
    // 4. 若下一步合法且未訪問,繼續;否則轉向
    if (ni >= 0 && ni < m && nj >= 0 && nj < n && !b[ni][nj]) {
        solve(ni, nj);
    } else {
        s++; // 轉向
        solve(i, j); // 原地重新嘗試新方向
    }
}

關鍵修正點

  • 統一入口檢查,避免重複代碼。
  • 使用 switch 替換多 if,確保單一方向執行。
  • 終止條件前置,滿足即返回,不再執行後續邏輯。
  • 轉向後原地遞歸,由入口檢查重新計算下一步。

調試建議

  • 添加 printf("solve(%d,%d) dir=%d\n", i, j, s%4); 觀察遞歸路徑。
  • 小矩陣(2x2, 3x3)手動跟蹤驗證邏輯。
  • 考慮改用迭代 + 方向向量數組,完全避免遞歸棧溢出風險。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved