日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

递归过程中语句执行顺序

發(fā)布時間:2024/7/5 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 递归过程中语句执行顺序 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

遞歸的兩種模式

模式一

//遞歸的過程中在"遞"的過程中解決問題 function function_name(Max_argument){if(end_condition){end;}else{solve;function_name(Min_argument);//問題規(guī)模逐漸減小} }

注:位于遞歸函數(shù)前的語句和函數(shù)具有順序性

模式二

//遞歸的過程中在"歸"的過程中解決問題 function function_name(Max_argument){if(end_condition){end;}else{function_name(Min_argument);//問題規(guī)模逐漸減小solve;} }

注:位于遞歸函數(shù)后的語句的執(zhí)行順序與原順序相反;
每一級的遞歸調(diào)用都擁有自己當前的局部變量,所以當調(diào)用對象的時候應(yīng)該注意是調(diào)用對象的非引用(復制對象), 以避免修改子對象造成對主問題的影響

調(diào)用棧

調(diào)用棧:描述函數(shù)之間的調(diào)用關(guān)系,當函數(shù)之間相互調(diào)用的時候會使用調(diào)用棧;
調(diào)用棧由多個棧幀組成,每個棧幀記錄著一個未運行完的函數(shù); 棧幀中保存著該函數(shù)的返回地址以及局部變量;
在遞歸中,遞歸函數(shù)的每一次的”遞進去”,棧幀都會將上個函數(shù)的返回地址局部變量保存以便在返回的過程中找得到相應(yīng)的”回歸出來的方向”

通過一個簡單的例子說明上述調(diào)用順序問題

//10進制轉(zhuǎn)2進制 void f(int n){if(n==0)return;printf("%d",n%2);//模式1,該模式下輸出語句將會是順序調(diào)用f(n/2) } //n=4,將輸出001,整個過程中先調(diào)用printf語句,然后"遞進去",通過棧幀進行回歸操作最終返回至main函數(shù)void f(int n){if(n==0)return;f(n/2)printf("%d",n%2) //模式2,整個過程中先執(zhí)行f 函數(shù)進行遞歸,到達遞歸基時返回執(zhí)行printf //整個過程中就是通過棧幀來記錄返回過程應(yīng)該執(zhí)行的printf,形成"回歸出來"解決問題,最終返回至main函數(shù) //n=4,輸出100 }

接下來將用斐波那契查找作為典型的例子證明尾遞歸的重要性:
看下面的一個錯誤的例子:

#include<iostream> using namespace std; int find(int a[],int lo,int hi,int e){int mid=(hi+lo)/2;if(e==a[mid]) return mid;if(e<a[mid]) {cout<<"lo_1="<<lo<<endl;find(a,lo,mid-1,e);}if(e>a[mid]){ find(a,mid+1,hi,e);cout<<"lo_2="<<lo<<endl;}if(lo>hi) {cout<<"lo_3="<<lo<<endl;return 0; }} int main(){//0,1,2,3,4,5,6,7,8,9 ,10,11,12,13,14,15,16,17 int a[]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18};cout<<find(a,0,17,18);return 0; } //斐波那契查找 這個例子證明了尾遞歸的重要,當前出現(xiàn)的問題是在遞歸過程中返回值具有隨機性,為正確將值返回,記住一條 //遞歸過程中棧幀的調(diào)用,到達遞歸基的時候返回出正確結(jié)果,但是經(jīng)過棧幀的調(diào)用后,正確的返回值返回給上一層調(diào)用函數(shù),上一層函數(shù)中未尋找到正確的值 //無法返回出正確的值,則返回出去一個隨機的值,導致最后答案錯誤, 正確的做法是將遞歸過程改為尾遞歸(return find(....)),直接終止程序(將后續(xù)的語句執(zhí)行停止) //就此返回出去的值只能是遞歸基時產(chǎn)生的值(每一層程序終止后所對應(yīng)的棧幀被清除,最后只保留著遞歸基中的棧幀) //原本打算采用else處理,不用return改為尾遞歸,但是失敗了,因為棧棧的緣故,每層的棧幀未清除,并且返回過程中沒有滿足條件的語句導致沒有返回值,最終無法 //完成尾遞歸的操作 //唉, 理解了遞歸過程,但是還未深刻理解尾遞歸的含義,莫大的悲哀,導致出現(xiàn)不該出現(xiàn)的錯誤

針對上述的操作進行修改

//斐波那契查找 /* #include<iostream> using namespace std; int f[]={0,1,1,2,3,5,8,13,21,34}; // 0 1 2 3 4 5 6 7 8 9 10 int find(int a[],int lo,int hi,int e){int k=0;while((hi-lo)>f[k]) {//斐波那契數(shù)列確定當前的黃金分割點k++;// cout<<"k"<<k<<endl;} int mid=lo+f[k-2]-1;//在中點求值出現(xiàn)錯誤,未正確表示中點位置 // int mid=(lo+hi)>>1; if(lo>=hi) {return 0;}//未命中目標if(e==a[mid]) return mid;if(e<a[mid]) {return find(a,lo,mid-1,e);}if(e>a[mid]) {return find(a,mid+1,hi,e);} } int main(){//0,1,2,3,4,5,6,7,8,9 ,10,11,12,13,14,15,16,17 int a[]={1,2,3,4,5,6,7,8,9};cout<<find(a,0,9,8);return 0; }

遞歸過程調(diào)用棧的使用與調(diào)用其他函數(shù)沒有區(qū)別,每一次的函數(shù)調(diào)用將會形成新的棧幀以保存上一次函數(shù)的返回地址和局部變量, 當棧幀中函數(shù)體執(zhí)行完成時將會刪除棧幀,處理返回值并修改當前代碼行
來自別人的話_很贊同__遞歸函數(shù)盡量不要有返回值或者基本類型的返回值(直接尾遞歸),如果要求必須有復雜類型返回值,寫成兩個函數(shù),遞歸函數(shù)不要有返回值,只是在函數(shù)中改變復雜類型的值;在驅(qū)動程序中定義復雜類型,調(diào)用遞歸函數(shù)返回復雜類型

總結(jié)

以上是生活随笔為你收集整理的递归过程中语句执行顺序的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。