2013年4月13日 星期六

遞迴基礎概念

說到遞迴真是無法馬上很清晰的明白整個過程
為了預防忘記,下面盡量使用較清晰方式記錄

比如1乘到5 等於 120
也可以寫成5!=120
數學原理如下
1*1=1
1*2=2
2*3=6
6*4=24
24*5=120
那~如何使用遞迴?
下面將使用到 "for 迴圈" 與 "呼叫副程式"
即可達到遞迴效果
先來看一下 簡單的遞迴程式碼

private void button2_Click(object sender, EventArgs e)
        {
            int g, y = 5;//先建立2個整數 一個=5代表終直
            g = SH(y);//g用來放SH(y)副程式,所傳回來的數值
            richTextBox1.Text = "計算結果:"+g + "\n";//將數值顯示出來
        }
        static int SH(int w)//呼叫副程式,這時候w=5
        {
            if (w == 0)//如果w=0回傳1
                return 1;
            else//不然w-1繼續呼叫副程式  一直到 w=0
                return w * SH(w - 1);
        }




 



來看一下
第一次呼叫副程式時w=5
5不等於0時
5-1在呼叫一次
5*sh(5-1)= 5*(戴回傳值)=?

第二次呼叫副程式w=4
4不等於0時
4-1再呼叫一次
4*sh(4-1)= 4*(戴回傳值)=?

第三次呼叫副程式w=3
3不等於0時
3-1再呼叫一次
3*sh(3-1)= 3*(戴回傳值)=?

第四次呼叫副程式w=2
2不等於0時
2-1再呼叫一次
2*sh(2-1)= 2*(戴回傳值)=?

第五次呼叫副程式w=1
1不等於0時
1-1再呼叫一次
1*sh(1-1)= 1*(戴回傳值)=?

第六次呼叫副程式w=0
0=0時 回傳1

之後倒著回傳回去

1*(回傳直1)=1

2*(回傳直1)=2

3*(回傳直2)=6

4*(回傳直6)=24

5*(回傳直24)=120

之後120傳回sh(y)=120
show出答案 120




再來 許多教材中
同時呼叫兩個副程式
來解釋遞迴概念

第一次接觸一定會花不少時間去思考
程式的步驟
下面將使用到 利用遞迴來判斷費式數列(Fibonacci)
誰知道啥事費式阿@@

必須先明白費式數列(Fibonacci)的意思才能明白程式的原理
對於數學不太好的我紀錄如下
來看一組 數字碼 如下
1、1、2、3、5、8、13、21、34、55、89
就像許多測試IQ的考古題 一時難以辨識這是啥?
試著嘗試 在字碼中找到規律?
下面講解 數字碼中的規律!!

費式數列中數列的前兩項為 1、1
在1 , 1 後面等數 等於 1+1=2
下一個數字則是
1+2=3
再來則是
2+3=5
以此類推~
就能明白 數字中的規律
公式是
Fn=(Fn-1)+(Fn-2)

題外話 值得一提
而黃金比例剛好是
Fn/Fn-1 =0.618或1.618
為何叫黃金比例
許多的生物構成都和斐波那契數列有正相關。例如人體腳底至頭頂之距離和從肚臍至腳底之距趨近\lim_{n \to \infty}\frac{F_n}{F_{(n-1)}} ,向日葵種子螺旋排列99%F_n



再來!
來看看如何使用第迴來計算費式數列
假如想知道 第幾幾階 有幾個節點


來看下面程式碼

private void btn_Get_Click(object sender, EventArgs e)
        {
            int P_int_temp;//定義整型變數
            //利用TryParse判斷有無輸入數值
            if (int.TryParse(txt_value.Text, out P_int_temp))
            {
                lb_result.Text = "結果為:" + Get(P_int_temp).ToString();
            }
            else
            {
                MessageBox.Show(//提示輸入正確數值
                    "請輸入正確的數值!", "提示!");
            }
        }
        /// <summary>
        /// 遞迴算法
        /// </summary>
        /// <param name="i">參與計算的數值</param>
        /// <returns>計算結果</returns>
        int Get(int i)
        {
            if (i <= 0)       //判斷數值是否小於0
                return 0;      //返回數值0
            else if (i >= 0 && i <= 2)   //判斷位數是否大於等於0並且小於等於2
                return 1;      //返回數值1
            else        //如果不滿足上述條件執行下面語句
                return Get(i - 1)+Get(i-2); //返回指定位數前兩位數的和
        }

要解釋程式執行過程需要深度的思考
有一點複雜還需要一點想像力!

假設 輸入4
Get(P_int_temp)等待傳回數值

第一次進入副程式
4有小於0嗎? 沒有
4有大於等於0 而且 小於等於2嗎?  沒有
再次呼叫2個副程式 分別是
get(4-1)+get(4-2),注意:將執行第二次副程式get(4-1) 而get(4-2)待命

第二次進入程式
4-1=3
3有小於0嗎? 沒有
3有大於等於0 而且 小於等於2嗎? 沒有
再次呼叫2個副程式 分別是
get(3-1)+get(3-2),注意:將執行第三次副程式get(3-1) 而get(3-2)待命

第三次進入復程式
3-1=2
2有小於0嗎? 沒有
2有大於等於0 而且 小於等於2嗎?  有
回傳get(3-1)數值1

注意
回到第二副程式
get(3-1)已傳回數值=1
開始執行剛才待命的Get(3-2)

第四次呼叫副程式
3-2=1
1有小於0嗎? 沒有
1有大於等於0 而且 小於等於2嗎? 有
回傳get(3-2)數值1

再次注意
第二副程式呼叫的兩個副程式
也傳回數值1
所以 在第二副程式中
get(1)+get(1) = 2
副程式2 已經算好了
數值2將 傳回
第一副程式

第一副程式中
get(4-1) 已收到傳回職2
get(2)+get(4-2)=?
開始執行待命的get(4-2)
 

get(4-2)將進入第五次呼叫副程式
4-2=2
2有小於0嗎? 沒有
2有大於等於0 而且 小於等於2嗎? 有
回傳get(3-1)數值1

回到第一次呼叫的副程式

get(傳回數值:2)+get(傳回數值:1)=3

Get(P_int_temp)等待傳回數值=3

答案=3

數字越大  越複雜 只需明白 程式運作順序即可如法炮製
在使用 遞迴 須注意到!!  型別大小
超出是會溢出的

沒有留言:

張貼留言