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

C 語言遞迴反轉字串輸出:完整程式碼、堆疊原理與尾遞迴優化

     編輯:程式設計綜合問答

題目要求

  • C 語言
  • 遞迴演算法
  • 反轉字串輸出 (如 "hello" → "olleh")
  • 不得使用迴圈

核心邏輯:後序遍歷 (遞迴深處先返回,再輸出)

字串 `"hello"` 在記憶體中:`h e l l o \0`
遞迴遞進:`foo("hello")` → `foo("ello")` → `foo("llo")` → `foo("lo")` → `foo("o")` → `foo("")` (基底返回)
遞歸歸出:印 `o` → 印 `l` → 印 `l` → 印 `e` → 印 `h` → **完成反轉**

完整程式碼 (含詳細註解)

#include 

/**
 * 遞迴反轉輸出字串
 * @param s 字串指標 (遞迴中不斷後移)
 */
void reversePrint(const char *s) {
    // 基底情況:字串結束符
    if (*s == '\0') {
        return; // 到達末端,開始回溯
    }

    // 遞迴處理下一字元 (遞進階段)
    reversePrint(s + 1);

    // 回溯階段:輸出當前字元
    putchar(*s); // 等同 printf("%c", *s),效率更高
}

int main() {
    char str[] = "hello world";
    printf("原始: %s\n", str);
    printf("反轉: ");
    reversePrint(str);
    printf("\n");
    return 0;
}

執行流程圖解 (堆疊幀)


呼叫堆疊 (遞進)                    返回輸出 (歸出)
┌─────────────────────┐           ┌─────────────────────┐
│ reversePrint("hello world") │ ← 最後返回 │ (無輸出)              │
│ reversePrint("ello world")  │           │ putchar('d') → 'd'  │
│ reversePrint("llo world")   │           │ putchar('l') → 'l'  │
│ reversePrint("lo world")    │           │ putchar('r') → 'r'  │
│ reversePrint("o world")     │           │ putchar('o') → 'o'  │
│ reversePrint(" world")      │           │ putchar(' ') → ' '  │
│ reversePrint("world")       │           │ putchar('d') → 'd'  │
│ reversePrint("orld")        │           │ putchar('l') → 'l'  │
│ reversePrint("rld")         │           │ putchar('r') → 'r'  │
│ reversePrint("ld")          │           │ putchar('o') → 'o'  │
│ reversePrint("d")           │           │ putchar('w') → 'w'  │
│ reversePrint("")            │ ── 基底 ── │ (返回)              │
└─────────────────────┘           └─────────────────────┘
最終輸出: "dlrow olleh"

輸出結果

原始: hello world
反轉: dlrow olleh

關鍵點解析

尾遞迴優化版 (需輔助函數/緩衝區)

純遞迴無法尾遞迴輸出 (輸出順序固定)。若需尾遞迴,**必須改為構建反轉字串再一次輸出**:


// 尾遞迴構建反轉字串 (需預分配緩衝區)
void reverseBuildTail(const char *src, char *dest, int idx) {
    if (*src == '\0') {
        dest[idx] = '\0';
        return;
    }
    reverseBuildTail(src + 1, dest, idx + 1);
    dest[idx] = *src; // 歸出時填入 (仍非尾遞迴)
}

// 真正尾遞迴:從尾端向前複製 (需先算長度)
void reverseCopyTail(const char *src, int len, char *dest, int pos) {
    if (pos == len) { dest[pos] = '\0'; return; }
    dest[pos] = src[len - 1 - pos];
    reverseCopyTail(src, len, dest, pos + 1); // 尾遞迴
}

總結

遞迴反轉字串輸出核心:**遞進不輸出、歸出輸出**,利用呼叫堆疊 LIFO 特性天然實現反序。程式碼極簡 (6 行)、邏輯清晰,是遞迴教學經典範例。**長字串注意堆疊溢位,實務請用迴圈或標準庫 `strrev`/`std::reverse`**。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
概念說明
遞進階段不斷 `s+1` 移動指標,**不輸出**,直到 `\0`
歸出階段函數返回時,**依序輸出** 當前 `*s`,形成反序
堆疊隱式儲存每層遞迴在堆疊保存 `s` 指標值,返回時自動還原
尾遞迴?**非尾遞迴** (遞迴呼叫後還有 `putchar`),無法編譯器優化,堆疊深度 = 字串長度
空間複雜度O(n) 堆疊深度,長字串 (超過 ~10⁵) 會堆疊溢位