1. 程式人生 > >關於遞迴(以一道題為例)輸出一個整數的每一位

關於遞迴(以一道題為例)輸出一個整數的每一位

題目:輸出一個整數的每一位

說明:這裡暫且不考慮負數的情況,只考慮正數

第一個程式碼:

思路:先考慮最極端的情況,當為一位數時,不再遞迴下去,輸出當前數字;否則不斷呼叫自身(引數中要依次丟棄每一位)

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>

void Printnum(int num)
{
	if (num < 10)
	{
		printf("%d", num);
	}

	Printnum(num / 10);
}


int main()
{
        int num = 0;
	scanf("%d", &num);
	Printnum(num);
}

 具體遞迴呼叫步驟

可以看到結果就是棧溢位。為什麼會這樣呢?因為程式執行的是“步驟”按“步驟”順序執行,以12為例,當num等於1時,進入if語句,輸出1;然後順序執行Printf(num/10),這時傳入的引數就變成了0,於是繼續呼叫函式,if條件滿足,輸出0,然後執行Printf(num/10)。因為引數一直為0,所以不斷輸出0,然後再順序呼叫,往復迴圈沒有出口。

錯的點是:遞迴始終沒有返回上一層。P(12)-->P(1)--->P(0)--->P(0)--->P(0)。。。。。

認識到上個程式碼存在的問題,於是改為這樣--->

第二個程式碼:

void Printnum(int num)
{
	if (num < 10)
	{
		printf("%d", num);
	}
	else
	{
		Printnum(num / 10);
	}
}

 具體遞迴呼叫步驟

 可以看到結果只輸出1。為什麼呢?以12為例,當num等於1時,進入if語句,輸出1;接下來不會進入else語句,但是會返回到遞迴的上一層,即Printnum(12),-->[要注意的是,這一層執行完後,遞迴就都結束了];直接跳出函式(注意不會執行裡面的else語句)。所以最終只會輸出1

再看這個-->(與第一個寫法類似,就是print語句稍有不同)

第三個程式碼:

void Printnum(int num)
{
	if (num < 10)
	{
		printf("%d", num%10);
	}
	Printnum(num / 10);
}

與第一個一樣,錯的點都是:遞迴始終沒有返回上一層。P(12)-->P(1)--->P(0)--->P(0)--->P(0)。。。。。

反思+總結:

遞迴一定是把握一個原則:“出口。”對於“出口”的理解,不是簡單的不滿足遞迴條件而“出”,而是從“大-->小>--大>”,一個大問題逐步分解為小問題,再小,直到最小的問題得到解決;然後再由小到大,依次一層層返回;最終到原點。

正確程式碼:

// 輸出一個整數的每一位。
void Printnum(int num)
{
	if (num > 9)
	{
		Printnum(num / 10);
	}
	printf("%d ", num % 10);
}

過程:P(12)-->P(1)-->最小問題解決-->P(12)-->函式結束

輸出結果: