欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C#函數(shù)式編程中的遞歸調(diào)用之尾遞歸詳解

 更新時(shí)間:2015年01月28日 09:20:52   投稿:junjie  
這篇文章主要介紹了C#函數(shù)式編程中的遞歸調(diào)用詳解,本文講解了什么是尾遞歸、尾遞歸的多種方式、尾遞歸的代碼實(shí)例等內(nèi)容,需要的朋友可以參考下

關(guān)于遞歸相信大家已經(jīng)熟悉的不能再熟悉了,所以筆者在這里就不多費(fèi)口舌,不懂的讀者們可以在博客園中找到很多與之相關(guān)的博客。下面我們直接切入正題,開始介紹尾遞歸。

尾遞歸

普通遞歸和尾遞歸如果僅僅只是從代碼的角度出發(fā)來看,我們可能發(fā)現(xiàn)不了他的特點(diǎn),所以筆者利用兩張堆棧上的圖來展示具體的差距在哪,首先我們來看看普通的遞歸調(diào)用的情況,如下圖1.1所示:

假設(shè)這里執(zhí)行的函數(shù)是Func1,并且Func1中通過遞歸調(diào)用了自己,那么我們可以看到棧上在每次調(diào)用Func1的時(shí)候都會(huì)重新將函數(shù)返回地址等其他參數(shù)放入棧中,在遞歸次數(shù)較少的情況下,這樣是不會(huì)有問題的。但如果遞歸調(diào)用次數(shù)達(dá)到一定的數(shù)量級(jí),則會(huì)將棧空間消耗光。因此,就提出了尾遞歸。而尾遞歸的棧圖如1.2所示:

一樣還是遞歸,但是每次執(zhí)行自身的時(shí)候并不會(huì)在??臻g中申請(qǐng)新的空間,類似于for循環(huán)的效果,面對(duì)遞歸次數(shù)很多的情況下也不會(huì)出現(xiàn)什么問題。但是新的問題就出來了,在C#中編譯器不會(huì)做到這一步優(yōu)化,而是在jit編譯器執(zhí)行時(shí)才會(huì)進(jìn)行優(yōu)化。并且只有64位才進(jìn)行優(yōu)化。在語(yǔ)言的層面上我們也要遵守一定的原則,才能讓編譯器知道去優(yōu)化。當(dāng)然有些喜歡看博客的人可能早就知道尾遞歸就是在最后return的時(shí)候調(diào)用自身。我們可以通過一串示意代碼來看尾調(diào)用:

復(fù)制代碼 代碼如下:

int Func1()
{
  return Func1();
}

當(dāng)然上面這串代碼會(huì)形成一個(gè)死循環(huán),因?yàn)檫@里我們沒有基線條件。下面我們舉一個(gè)例子:

這個(gè)函數(shù)想必應(yīng)該會(huì)比較熟悉,就是計(jì)算階乘的。但是我們可以發(fā)現(xiàn)函數(shù)sunfc最后的返回語(yǔ)句并不是直接調(diào)用函數(shù)本身,而是x*sfunc(x -1),恰恰就是因?yàn)榍懊孢@個(gè)x*就會(huì)導(dǎo)致編譯器無法優(yōu)化,從而只能采用普通的遞歸調(diào)用的方式去執(zhí)行,那么我們就需要利用一些模式去改變,首先我們先介紹的是“累加器傳遞模式”,可能名字比較懸乎,其實(shí)就是將當(dāng)前的計(jì)算結(jié)果傳遞給下一次調(diào)用函數(shù)中,這樣當(dāng)?shù)竭_(dá)基線條件后直接根據(jù)上次計(jì)算的結(jié)果算出最終結(jié)果返回即可,如果將上面的代碼采用這個(gè)模式就是下面這個(gè)樣子:

采用這個(gè)模式之后我們就變回了尾遞歸了,當(dāng)執(zhí)行到基線條件時(shí),直接返回y的值即可。根本不需要回溯到以前。除了利用這種模式,我們還可以利用一種“后繼傳遞模式”,跟累加器傳遞模式一樣也需要修改函數(shù)簽名,增加一個(gè)參數(shù),我們繼續(xù)修改上面這串代碼:

 

相比累加器傳遞模式,這種方式比較難理解,其實(shí)sfunc在到達(dá)基線條件時(shí)y就等同于下面這個(gè)lambda表達(dá)式:a => a*4*3*2,然后就是調(diào)用y(1)就直接計(jì)算最終的結(jié)果了。在簡(jiǎn)單點(diǎn)就是y這個(gè)函數(shù)被包裝了了好幾層,比如上面這段函數(shù)執(zhí)行結(jié)束時(shí)y的調(diào)用順序:

a為1傳遞給y(2 * a),結(jié)果就是y(2)。

a為2傳遞給y(3 * a),結(jié)果就是y(6)。

a為6傳遞給y(4 * a),結(jié)果就是y(24)。

a為24傳遞給x => x,輸出24。


如果還是不理解只能下斷點(diǎn),調(diào)試自己琢磨琢磨了,實(shí)在不懂的可以Q問。

 

在滿足必要的經(jīng)濟(jì)的條件下,研究更加高深的技術(shù).滿足自己的野心

相關(guān)文章

  • 利用C#實(shí)現(xiàn)修改圖片透明度功能

    利用C#實(shí)現(xiàn)修改圖片透明度功能

    這篇文章主要為大家詳細(xì)介紹了如何利用C#實(shí)現(xiàn)修改圖片透明度功能,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)C#有一定的幫助,感興趣的小伙伴可以了解一下
    2022-12-12
  • C#縮略圖多路徑多格式保存的實(shí)例

    C#縮略圖多路徑多格式保存的實(shí)例

    這篇文章介紹了C#縮略圖多路徑多格式保存的實(shí)例,有需要的朋友可以參考一下
    2013-07-07
  • C語(yǔ)言使用getch()讀取方向鍵

    C語(yǔ)言使用getch()讀取方向鍵

    getch()是編程中所用的函數(shù),這個(gè)函數(shù)是一個(gè)不回顯函數(shù),當(dāng)用戶按下某個(gè)字符時(shí),函數(shù)自動(dòng)讀取,無需按回車,有的C語(yǔ)言命令行程序會(huì)用到此函數(shù)做游戲,但是這個(gè)函數(shù)并非標(biāo)準(zhǔn)函數(shù),要注意移植性
    2021-07-07
  • 詳解C#中委托,事件與回調(diào)函數(shù)講解

    詳解C#中委托,事件與回調(diào)函數(shù)講解

    這篇文章主要介紹了詳解C#中委托,事件與回調(diào)函數(shù)講解,小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。
    2016-12-12
  • 基于.net中突破每客戶端兩個(gè)http連接限制的詳細(xì)介紹

    基于.net中突破每客戶端兩個(gè)http連接限制的詳細(xì)介紹

    本篇文章是對(duì).net中突破每客戶端兩個(gè)http連接限制進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05
  • SuperSocket封裝成C#類庫(kù)的步驟

    SuperSocket封裝成C#類庫(kù)的步驟

    這篇文章主要介紹了SuperSocket封裝成C#類庫(kù)的步驟,幫助大家更好的理解和使用c#,感興趣的朋友可以了解下
    2021-01-01
  • C#使用SqlConnection連接到SQL Server的代碼示例

    C#使用SqlConnection連接到SQL Server的代碼示例

    這篇文章主要介紹了C#使用SqlConnection連接到SQL Server的代碼示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-03-03
  • C#使用LINQ查詢操作符實(shí)例代碼(二)

    C#使用LINQ查詢操作符實(shí)例代碼(二)

    這篇文章介紹了C#使用LINQ查詢操作符的方法,文中通過示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-06-06
  • C#簡(jiǎn)易圖片格式轉(zhuǎn)換器實(shí)現(xiàn)方法

    C#簡(jiǎn)易圖片格式轉(zhuǎn)換器實(shí)現(xiàn)方法

    這篇文章主要介紹了C#簡(jiǎn)易圖片格式轉(zhuǎn)換器實(shí)現(xiàn)方法,涉及C#基于WinForm操作圖片的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-11-11
  • c#基礎(chǔ)系列之System.String的深入理解

    c#基礎(chǔ)系列之System.String的深入理解

    這篇文章主要給大家介紹了關(guān)于c#基礎(chǔ)系列之System.String的深入理解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-09-09

最新評(píng)論