1. 程式人生 > >遞迴函式詳解

遞迴函式詳解

遞迴函式就是在函式體內部呼叫自己的函式

眾所周知,遞迴思維在程式設計界影響深遠,一重遞迴簡單明瞭,很容易看出執行順序,但是遞迴有了巢狀後,你是否還能理解其執行過程呢?

1.單重遞迴。

#include<iostream>
#include<string>


using namespace std;


int m = 5,n = 5;


void view(string sign,int value);
void resault();


int main(int argc,char** argv){

resault();

return 0;
}


void resault(){

view("m",m);
}


void view(string sign,int value){

if(value > 0){

cout << sign << " = " << value << endl;
value--;

view(sign,value);
}
}


這種遞迴是最簡單的遞迴,也非常容易理解,故在此不多浪費口舌.

2.並列遞迴

#include<iostream>
#include<string>


using namespace std;


int m = 5,n = 5;


void view(string sign,int value);
void resault();


int main(int argc,char** argv){

resault();

return 0;
}


void resault(){

view("m",m);
view("n",n);
}


void view(string sign,int value){


if(value > 0){

cout << sign << " = " << value << endl;
value--;

view(sign,value);
}

}


這種遞迴不涉及巢狀,兩個遞迴同等級同地位,也屬於簡單遞迴。

3.遞迴巢狀

#include<iostream>
#include<string>
#include<Windows.h>


using namespace std;


int m = 5,n = 5;


void view(string sign,int value);
void resault();


int main(int argc,char** argv){

resault();

return 0;
}


void resault(){

view("m",m);
}


void view(string sign,int value){

if(value > 0){

cout << sign << " = " << value << endl;
value--;
view("n",value);
view(sign,value);

}else{

return;
}

}


這種遞迴就屬於遞迴的嵌套了,與前邊相比,就上升了一個檔次,有了一定的難度,聰明的你們知道其執行順序的原理麼?

因為遞迴具有一定的等級性,把每一層的引數都壓在了堆疊當中,系統開銷大,而且很容易造成堆疊的溢位,所以對思維有一定的要求,否則很容易造成堆疊溢位或者死迴圈。為什麼說它具有等級性呢,因為他要呼叫自己本身,不一定呼叫一次,而每一次呼叫時引數會隨著改變,那麼,問題就來了,執行順訊應該怎麼理解,就比如上圖,其實,從執行結果來看,不難看出遞迴確實與棧有著千絲萬縷的聯絡,特別是存在遞迴巢狀的時候,就比如上圖,假如我們用p表示外層遞迴,q來表示內層遞迴巢狀,如果程式碼是這樣的(虛擬碼)

work(){

    p(n)->work();

    q(n)->work();

}

假使當n達到3以後就滿足該遞迴出口的條件,那麼這個遞迴函式的執行順序就是

p1->p2->p3->q3->q2->p3->q3->q1->p2->p3->q3->q2->p3->q3

光看是看不出什麼名堂來的,下面我們通過分析上一個題的執行過程來更清楚瞭解巢狀遞迴函式的執行順序:


聰明的你是否看出了什麼名堂?

我再幫你做點啥吧:


這下,你應該茅塞頓開了吧,所以你會得出結論,遞迴巢狀的執行順序具有以下性質:

1.先執行當前遞迴函式(外層)(序號1)的第一個雙重遞迴函式(內層)(序號2),然後並不立即執行該遞迴函式(序號1)的第二個雙重遞迴函式(內層),而是執行第一個雙重遞迴函式(序號2)的第一個三重雙重包含函式(序號3),假設三重遞迴函式執行完畢滿足遞迴出口,第一個三重遞迴函式執行完畢後,它會找與自己同等級(源自同一個雙重遞迴函式)的下一個三重遞迴函式(序號4),如果沒有(如果序號4不存在),返回到該三重遞迴函式(序號3)的來源遞迴函式(第一個雙重遞迴函式)(序號2),檢視第一個雙重遞迴函式(序號2)是否存在同等級遞迴函式,以此類推......

2.第n重遞迴函式執行順序的優先順序為:

第一個n+1重遞迴函式 > 同等級n+1重遞迴函式(第二個n+1重遞迴函式) > 該n重遞迴函式的源n-1重遞迴函式

簡單的理解為有兒子就給兒子,沒兒子就給弟弟,兒子弟弟都沒有就給父親,這裡充分的體現出了遞迴函式的原型類似於資料結構棧的原理.

可以看出,其執行順序並不是我們人類的常規思維(類廣度優先遍歷),而是類深度優先遍歷,即使這樣,程式依然能不按遞迴等級變化完美的記憶不同等級,不同順序的遞迴函式用到的引數及變數,只說明瞭一個問題,它是依據資料結構的棧的原理,不斷開闢新的記憶體空間以滿足程式需要,而不是不斷改變已有記憶體空間的值來滿足程式需要,所以遞迴是一種極具消耗記憶體資源的演算法思維,所以在現實專案中,除非程式碼量影響過大,否則能不用遞迴就不用遞迴.

相關推薦

PYTHON 函式

Python 遞迴函式 詳解 在函式內呼叫當前函式本身的函式就是遞迴函式 下面是一個遞迴函式的例項: 第一次接觸遞迴函式的人,都會被它呼叫本身而搞得暈頭轉向,而且看上面的函式呼叫,得到的結果會是: 為什麼會得出上面的結果呢?因為都把呼叫函式本身之後的程式

函式

遞迴函式就是在函式體內部呼叫自己的函式眾所周知,遞迴思維在程式設計界影響深遠,一重遞迴簡單明瞭,很容易看出執行順序,但是遞迴有了巢狀後,你是否還能理解其執行過程呢?1.單重遞迴。#include<iostream>#include<string>usi

定義函式

函式:就是功能(實現這個功能的過程)  1、定義函式:     返回值  函式名(形參)     {     }     static 返回值 函式名(形參)     {     } 注:如果被修飾為static,此函式只能被本地呼叫。 2、呼叫函式:執行一次函式 注

演算法

1. 何為遞迴? 遞迴在我們的生活中其實很常見。假設你去電影院看電影,黑漆漆一片,你不知道自己來到了第幾排,於是你問前面的人他是第幾排,知道了前面的人是第幾排,加一也就是你所在的排數。但前面的人也不知道,於是他也繼續向前問,直到第一排的人回答他在第一排,然後再依次往後傳,最後

圖的深度優先遍歷(非+

圖的深度優先遍歷 非遞迴演算法: #include<iostream> #include<stack> using namespace std; const int MaxSize=100; class MGraph{//鄰接矩陣的構建 p

LeetCode 856 思路

題目描述 給定一個平衡括號字串 S,按下述規則計算該字串的分數: () 得 1 分。 AB 得 A + B 分,其中 A 和 B 是平衡括號字串。 (A) 得 2 * A 分,其中 A 是平衡括號字串。

入門(十) ---- 列印數字(原理)

wechat:812716131 ------------------------------------------------------ 技術交流群請聯絡上面wechat ----------------------------------------------

HDU - 1995 奇妙的塔 (漢諾塔思想

用1,2,...,n表示n個盤子,稱為1號盤,2號盤,...。號數大盤子就大。經典的漢諾塔問  題經常作為一個遞迴的經典例題存在。可能有人並不知道漢諾塔問題的典故。漢諾塔來源於  印度傳說的一個故事,上帝創造世界時作了三根金剛石柱子,在一根柱子上從下往上按大小 

全排列演算法

一、概述 全排列在很多程式都有應用,是一個很常見的演算法,常規的演算法是一種遞迴的演算法,這種演算法的得到基於以下的分析思路。 給定一個具有n個元素的集合(n>=1),要求輸出這個集合中元素的所有可能的排列。 二、遞迴實現 2.1、例項一

呼叫,分析呼叫的詳細過程

一、棧      在說函式遞迴的時候,順便說一下棧的概念。      棧是一個後進先出的壓入(push)和彈出(pop)式資料結構。在程式執行時,系統每次向棧中壓入一個物件,然後棧指標向下移動一個位置。當系統從棧中彈出一個物件時,最近進棧的物件將被彈出。然後棧指標向上移動一個位置。程式設計師經常利用棧這種資料

二叉樹3種遍歷演算法與非實現

一, 二叉樹先序遍歷的實現     遞迴實現 void PreOrderTraverse(BiTree T) { if( T ) { VisitF(T->data);//訪問根節點 PreOrderTra

C++ (一)

這幾天看了一下遞迴 1.遞迴 遞迴:一個物件部分地由它自己組成或定義,稱為遞迴。 遞迴函式:一個函式直接或間接地呼叫自身。 遞迴呼叫:在呼叫一個函式的過程中又出現直接或間接地呼叫該函式本身,稱為函式的

Oracle 查詢

建立表和主外來鍵 CREATE TABLE SC_DISTRICT ( ID NUMBER(10) NOT NULL, PARENT_ID NUMBER(10), NAME VARCHAR2(

如何僅用函式和棧操作逆序一個棧(版)

import java.util.Stack; public class ReverseStack { /** * 1、首先,取出棧頂元素 * 2、然後求剩下元素的最後一個元素 * 3

C++ 函式

說到遞迴函式,就會想起遞迴的快速排序。 1.快速排序是什麼呢? 快速排序的基本思想是:通過一趟快速排序,把待排記錄分成兩 個子序列,其中一個子系列中的記錄都小於另一個子序列,然後, 分別對兩個子序列進

十一、Go基礎程式設計:函式函式型別、匿名函式與閉包

1. 遞迴函式 遞迴指函式可以直接或間接的呼叫自身。 遞迴函式通常有相同的結構:一個跳出條件和一個遞迴體。所謂跳出條件就是根據傳入的引數判斷是否需要停止遞迴,而遞迴體則是函式自身所做的一些處理。 //通過迴圈實現1+2+3……+100 func Test01() int { i

MySQL 的函式

完整性約束 什麼是資料完整性 資料的準確性和可靠性。 分類 實體完整性 記錄準確的。(記錄不能重複) 主鍵約束: 不能重複,不能為空。  Primary key 欄位唯一的。 不能使用業務欄位。 無意義的

函式使用例項

一.建立遞迴陣列 //$fid 父id $v['id'] 子id $v['child'] 子id陣列 //$cate 要迴圈的一維陣列 function digui($cate, $fid = 0){ foreach ($cate as $v)

Vue生命週期函式

 vue例項的生命週期 1 什麼是生命週期(每個例項的一輩子) 概念:每一個Vue例項建立、執行、銷燬的過程,就是生命週期;在例項的生命週期中,總是伴隨著各種事件,這些事件就是生命週期函式; 生命週期:例項的生命週期,就是一個階段,從建立到執行,再到銷燬的階段; 生命週期函式:在例項的生命週

Python全棧學習筆記day 17:函式之:二分法(老男孩Python全棧學習s9 day17 二分法程式有些問題)

遞迴函式 遞迴 : 在函式中呼叫自身函式 最大遞迴深度預設是997/998 —— 是python從記憶體角度出發做得限制 二分法: 實現程式: 最基礎版:(很多問題:切分導致出現了新列表,無法返回元素在 l 中的位置) l = [2,3,5,10,15,16,