国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > C# > 正文

C#中尾遞歸的使用、優化及編譯器優化

2020-01-24 02:01:03
字體:
來源:轉載
供稿:網友

遞歸運用

一個函數直接或間接的調用自身,這個函數即可叫做遞歸函數。

遞歸主要功能是把問題轉換成較小規模的子問題,以子問題的解去逐漸逼近最終結果。
遞歸最重要的是邊界條件,這個邊界是整個遞歸的終止條件。

復制代碼 代碼如下:

static int RecFact(int x)
{
    if (x == 0)
        return 1;
    return x * RecFact(x - 1);
}
RecFact(10);

上面是個經典階乘函數的實現。這里分2步:

1.轉換,把10的階乘轉化成10*9!,10(9*8!)....每次轉換規模就變的更小。
2.逼近,轉換到最小規模時0!,求解1。開始逆向合并逐漸逼近到10,得出解。
這里的x==0就是我們的邊界條件(即終止條件),也有的依賴外部變量為邊界。

如果一個遞歸函數沒有邊界,也就無法停止(無限循環至內存溢出),當然這樣也沒什么意義。

RecFact調用堆棧:

常見使用場景:

1.階乘/斐波那契數列/漢諾塔
2.遍歷硬盤文件
3.InnerExceptions異常撲捉(exception.InnerException==null)

尾遞歸優化

當邊界不明確的時候,遞歸就很容易出現溢出問題。

在階乘過程中,堆棧需要保存每次(RecFact)調用的返回地址及當時所有的局部變量狀態,期間堆棧空間是無法釋放的(即容易出現溢出)。

為了優化堆棧占用問題,從而提出尾遞歸優化的辦法。

復制代碼 代碼如下:

static void TailRecursion(int x)
    {
        Console.WriteLine(x);
        if (x == 10)
            return;
        TailRecursion(x + 1);
    }
    TailRecursion(0);

使用尾遞歸堆棧可以不用保存上次的函數返回地址/各種狀態值,而方法遺留在堆棧上的數據完全可以釋放掉,這是尾遞歸優化的核心思想。

由于尾遞歸期間,堆棧是可以釋放/再利用的,也就解決遞歸過深而引起的溢出問題,這也是尾遞歸的優勢所在。

編譯器優化

尾遞歸優化,看起來是蠻美好的,但在net中卻有點亂糟糟的感覺。

1.Net在C#語言中是JIT編譯成匯編時進行優化的。
2.Net在IL上,有個特殊指令tail去實現尾遞歸優化的(F#中)。

我們執行 TailRecursion(0)(x==1000000) 得出如下結論:

C#/64位/Release是有JIT編譯器進行尾遞歸優化的(非C#編譯器優化)。

C#/32位或C#/Debug模式中JIT是不進行優化的。

F#在優化尾遞歸也分2種情況:

1、 簡單的尾遞歸優化成while循環,如下:

復制代碼 代碼如下:

let rec TailRecursion(x) =
  if (x = 1000) then true
  else TailRecursion(x + 1)

(方便演示C#呈現)編譯器優化成:
復制代碼 代碼如下:

public static bool TailRecursion(int x)
    {
        while (x != 0x3e8)
        {
            x++;
        }
        return true;
    }

2、 復雜的尾遞歸,F#編譯器會生成IL指令Tail進行優化,如下:
復制代碼 代碼如下:

let TailRecursion2 a cont = cont (a + 1) 

優化成:

如何定義復雜的尾遞歸呢?通常是后繼傳遞模式(CPS)。

F#中在debug模式下,需要在編譯時配置:

總結

在C#語言(過程式/面向對象編程思想)中,優先考慮的是循環,而不是遞歸/尾遞歸。 但在函數式編程思想當中,遞歸/尾遞歸使用則是主流用法,就像在C#使用循環一樣。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 康保县| 社会| 略阳县| 乐清市| 大新县| 亳州市| 武强县| 汶川县| 阳城县| 仪陇县| 谢通门县| 玉山县| 蓬安县| 义马市| 文成县| 绥中县| 涡阳县| 宁陕县| 宣恩县| 南阳市| 日喀则市| 绍兴县| 华池县| 海城市| 岢岚县| 华容县| 青海省| 安多县| SHOW| 多伦县| 绍兴市| 固安县| 丰镇市| 龙南县| 安泽县| 郸城县| 博白县| 宁陕县| 盐源县| 娄烦县| 高清|