1. 程式人生 > >C語言遞迴算法系列_ 逆序和正序輸出一個整數的每位數 (1)

C語言遞迴算法系列_ 逆序和正序輸出一個整數的每位數 (1)

  這是一個簡單的問題,也是遞迴裡面比較典型的例子。那麼從這裡開始我們的遞迴之旅。

參考書籍《資料結構與演算法分析 C語言描述》 《Java程式設計 基礎、程式設計抽象與演算法策略》

  先談談遞迴,遞迴的一般解釋為將問題分解為更簡單的具有類似解決方法子問題,更小子問題解決後將結果一步步返還給原始問題。這個過程通俗來講就是函式自己呼叫自己。用遞迴解決問題的過程體現了分而治之的演算法策略。

遞迴解題的一般步驟為:

1.抽象出問題的最簡單模型或者說遞迴的終止條件。比如我們後面要求的階乘,最簡單的形式為n < 2,結果返回1;

2.抽象出遞迴的一般形式。 比如我們求階乘, n!的結果依賴與(n-1)!,找出一般形式 n! = n * (n - 1)!。

思考遞迴的過程要求我們著眼於大局,而不糾結於哪一細節。

下面就按步驟來分析我們遞迴順序輸出整數各個位的過程:

a.考慮最簡單的情況

最簡單的肯定是一位數,所有此時直接printf n, return 讓遞迴函式結束,就有這樣的形式

if (n 為個位數)
    {
        print(n)
        return ;
    }

b.如果不是這種情況,我們就得繼續分析。

既然是順序,我們就要第一位輸出最高位,第二位輸出次高位,最後輸出個位。我們知道,函式的呼叫是通過棧來實現的。要將最高位輸出,我們必須在棧滿的時候輸出它。換句話說,我們得通過不斷/10來讓遞迴呼叫的引數削到只剩最高位一位,就回到了我們最簡單的情況,將最高位輸出,引數為一位的那個遞迴函式就彈棧釋放了,然後就返還到引數為最高位和次高位組成引數的遞迴函式版本了。依次類推,最後打印出所有的位數來。

所以,遞迴函式(假如為order_print)在上面程式碼段下應該一如下程式碼段

 order_print(n / 10);
 print(n % 10);
這裡的%10在函式回溯返回時得到當前引數“個位”的, 以n = 123為例,我們看看函式的呼叫過程:

每一層代表一個函式,左側代表入棧,右側表示出棧,程式從main()函式開始,最後回到main函式。左側方塊上的n表示當前函式的引數n,往下依次/10,所以n為123,12,1。


至於逆序輸出,我們可以按照這個步驟來思考,可以參考下面程式碼。大家可以看到輸出格式並不相同,大家如果弄明白這個過程就知道了。

下面給出完整程式:

#include <stdio.h>

void order_print(int n)
{
    if (n < 10)
    {
        printf("%d", n);
        return ;
    }
    order_print(n / 10);
    printf("%5d", n % 10);
}

void reverse_print(int n)
{
    
    if (n < 10)
    {
		printf("%-5d", n);
        return;
    }
	printf("%-5d", n % 10);
    reverse_print(n / 10);

}

int main(void)
{
    int n;
    printf("Input a integer: ");
    scanf("%d", &n);
    printf("Order print:");
    order_print(n);
    printf("\n");
    printf("Reverse print:");
    reverse_print(n);
    return 0;
}

執行示例:


好了,學習遞迴的第一步,從簡單的輸出開始,讓我們繼續前進吧!