• 
    

    
    

      99热精品在线国产_美女午夜性视频免费_国产精品国产高清国产av_av欧美777_自拍偷自拍亚洲精品老妇_亚洲熟女精品中文字幕_www日本黄色视频网_国产精品野战在线观看

      ?

      C語言遞歸函數(shù)教學(xué)的設(shè)計(jì)與探討

      2018-09-14 10:27丁雪晶
      電腦知識與技術(shù) 2018年16期
      關(guān)鍵詞:案例分析C語言教學(xué)設(shè)計(jì)

      丁雪晶

      摘要:針對《C語言程序設(shè)計(jì)》課程,在教學(xué)過程中遞歸函數(shù)部分普遍反映比較難,文章給出了遞歸函數(shù)的定義和設(shè)計(jì)思路,并通過對幾大典型的遞歸問題給出求解思路和參考代碼,加強(qiáng)學(xué)生對遞歸函數(shù)的理解,提高學(xué)生對遞歸函數(shù)的掌握和應(yīng)用。

      關(guān)鍵詞:C語言;遞歸函數(shù);教學(xué)設(shè)計(jì);案例分析

      中國分類號:G424 文獻(xiàn)標(biāo)識碼:A 文章編號:1009-3044(2018)16-0150-03

      1引言

      《C語言程序設(shè)計(jì)》是高等學(xué)校計(jì)算機(jī)及相關(guān)專業(yè)的必修課,其以短小精悍、使用靈活、功能強(qiáng)大等特點(diǎn)深受人們的喜愛。函數(shù)作為C語言程序設(shè)計(jì)的基本組成單位,在教學(xué)過程中占據(jù)著非常重要的地位,而遞歸函數(shù)的設(shè)計(jì)則是函數(shù)教學(xué)中的重點(diǎn)和難點(diǎn)。

      2遞歸函數(shù)概述

      在編程語言中,函數(shù)直接或間接調(diào)用函數(shù)本身,該函數(shù)稱為遞歸函數(shù)[1]。但遞歸也并不是簡單的“自己調(diào)用自己”。遞歸算法的思想是:把要解決的問題分解成與原問題有相同解法,且規(guī)模較小的問題,直到遇見終止條件。

      所以一般情況下,能采用遞歸函數(shù)來解決的問題,需滿足以下兩個(gè)條件:

      (1)該問題可以縮小規(guī)模,且縮小后的問題與原問題有相同的解法;

      (2)必定要有一個(gè)明確的結(jié)束遞歸的條件。

      為了方便理解,以求n!為例,這是一個(gè)明顯的可以用遞歸解決的問題:

      n!可以表示為:[n!=n×n-1×n-2…×2×1=n×n-1!]

      即有:

      [n!=1 n=1n×n-1! n>1 ]

      或者

      [f(n)=1 n=1n×f(n) n>1 ]

      首先看看該問題是否滿足遞歸的兩個(gè)條件的:

      當(dāng)n>=2,求f(n)只需求出f(n-1),也就是說求n的階乘問題,轉(zhuǎn)化成了規(guī)模更小的求n-1階乘問題;

      而遞歸結(jié)束條件為,n=1時(shí), fun(1) = 1。

      因此,我們可以很容易的寫出計(jì)算n!的遞歸程序:

      int fac(int n)

      {

      if(n==1)

      return 1;

      else

      return n*fac(n-1);

      }

      在編寫遞歸函數(shù)時(shí),通常把判斷遞歸結(jié)束的條件寫在前面,以確保函數(shù)在遇到結(jié)束條件時(shí)能中止遞歸,否則會(huì)導(dǎo)致程序死循環(huán)。

      3 典型案例分析

      例1:求Fibonacci數(shù)列(斐波那契)的第n項(xiàng)值,表示如下:

      [fibn=1 ,n=0或 n=1fibn-1+fibn-2, n>1]

      此例將求規(guī)模為n的問題轉(zhuǎn)化為規(guī)模較小的n-1和n-2問題,而遞歸結(jié)束條件為,一直轉(zhuǎn)化到規(guī)模為1和0時(shí)。所以遞歸函數(shù)設(shè)計(jì)如下:

      int fib(int n)

      {

      if(n==1 || n==2)

      return 1;

      else

      return fib(n-1)+fib(n-2);

      }

      void main()

      {

      int num=fib(8);

      printf("%d",num);

      }

      輸出結(jié)果:21

      例2:漢諾塔問題[1]:有三根桿子A,B,C。A桿上有若干盤子,把所有盤子從A桿移到C桿(可借助B桿)。規(guī)則是:每次只能移動(dòng)一個(gè)盤子,且在移動(dòng)過程中三根桿上都始終保持大盤在下,如圖1所示。求移動(dòng)的步驟和移動(dòng)的次數(shù)。

      實(shí)現(xiàn)這個(gè)漢諾塔問題的遞歸算法可以有如下步驟(n表示盤的個(gè)數(shù),從上往下依次為第1個(gè),第2個(gè)…第n個(gè)):

      當(dāng)n=1時(shí),即只有一個(gè)盤子,為遞歸算法的結(jié)束條件,從A盤移到C盤即可;

      當(dāng)n>=2時(shí):

      (1)先將A柱上面的n-1個(gè)盤子從A柱借助C柱,移到B柱;

      (2)將A柱的第n個(gè)盤子從A柱移動(dòng)C柱;

      (3)再將B柱的n-1個(gè)盤子借助A柱,移到C柱。

      將漢諾塔的規(guī)模為n的問題轉(zhuǎn)化為規(guī)模小一點(diǎn)的n-1問題,通過遞歸會(huì)將規(guī)模繼續(xù)減小,直到遇到結(jié)束條件的規(guī)模為1的問題。

      遞歸算法hanoi實(shí)現(xiàn)如下:

      #include

      int num=0;

      void hanoi(intn,charA,charB,char C)//將n個(gè)盤子從A柱,借助B柱,移動(dòng)C柱

      {

      if(n==1)//結(jié)束條件

      {

      num++;

      printf("第%d次:%d號盤:%c——>%c\n",num,n,A,C);

      }

      else

      {

      hanoi(n-1,A,C,B); //n-1個(gè)盤子從A柱借助C柱,移到B柱

      num++;

      printf("第%d次:%d號盤:%c——>%c\n",num,n,A,C);

      hanoi(n-1,B,A,C);//n-1個(gè)盤子從B柱借助A柱,移到C柱

      }

      }

      void main()

      {

      hanoi(3,'A','B','C');//將3個(gè)盤子從A移到C

      }

      實(shí)驗(yàn)結(jié)果如圖2所示:

      例3:八皇后問題[2]

      八皇后問題是一個(gè)以國際象棋問題:如何在8×8的棋盤上擺8個(gè)皇后,每行每列只能擺一個(gè)皇后,使得這8個(gè)皇后無法相互攻擊,即任意的2個(gè)皇后不能在同一行、同一列或?qū)蔷€上,如圖3所示。當(dāng)然這是八皇后問題的初始規(guī)則,現(xiàn)在可以將其推廣為四皇后,五皇后等n皇后問題,此處的n須等于1或大于等于4,問題才有解。

      解題思路:

      從第一行開始擺放皇后,每擺放1行,遞歸一次,每次遞歸里面考慮8列, 即對每一行皇后有8個(gè)可能的位置可以放。找到一個(gè)與前面行的皇后都不會(huì)互相攻擊的位置,然后再遞歸進(jìn)入下一行。

      在這里用一個(gè)一維數(shù)組來表示相應(yīng)行對應(yīng)的列,即k[i]=j表示,第i行的皇后放在第j列?;屎螽a(chǎn)生沖突的條件有3個(gè):同行、同列、對角線。例如對于m行和n行擺放皇后時(shí)的沖突:同列:k[m]=k[n]。對角線有主對角線方向和副對角線方向。主對角線滿足,兩個(gè)皇后的行之差等于他們的列之差:m-n=k[m]-k[n]; 副對角線方向, 兩個(gè)皇后的行之差等于其列之差的相反數(shù):m-n=k[n]-k[m]。 只有當(dāng)前皇后和前面所有已擺好的皇后都不會(huì)產(chǎn)生沖突時(shí),才能進(jìn)行下一個(gè)皇后的擺放,即下一級遞歸。

      遞歸函數(shù)設(shè)計(jì)如下:

      #include

      intk[4], n=4, num=0; //n設(shè)為4,即4行4列

      void print(){ //輸出皇后矩陣,擺了皇后輸出1,沒擺皇后輸出0

      for(int i=0; i

      for(int j=0; j

      if(k[i]==j)

      printf("1 ");

      else

      printf("0 ");

      printf("\n");

      }

      printf("\n");

      }

      voidfun(int r){

      int flag=0;

      if(r == n){//當(dāng)擺完最后一行時(shí),輸出皇后矩陣,遞歸結(jié)束條件

      print();

      num++;

      return;

      }

      for(int i=0; i

      k[r] = i;//第r行的皇后位置放在i列

      flag=1;

      for(int j=0; j

      if(k[r]==k[j] || r-j==k[r]-k[j] || r-j==k[j]-k[r]){//產(chǎn)生沖突的條件

      flag=0;

      break;

      }

      if(flag)

      fun(r+1); //進(jìn)入下一級遞歸,即擺放第r+1個(gè)皇后

      }

      }

      void main(){

      fun(0);

      printf("共%d種擺放\n",num);

      }

      實(shí)驗(yàn)結(jié)果如圖4所示:

      例4:二叉樹的遍歷[3]

      一棵二叉樹由根結(jié)點(diǎn)、左子樹和右子樹三部分組成,因而只要依次遍歷這三個(gè)部分,就能遍歷整棵二叉樹的所有結(jié)點(diǎn)。遍歷方式有先序遍歷(先根結(jié)點(diǎn),然后。左子樹右子樹)、中序遍歷(先左子樹,然后根結(jié)點(diǎn),最后右子樹)、后序遍歷(先左子樹、右子樹,然后根結(jié)點(diǎn)),這三種遍歷算法采用遞歸方式比非遞歸方式要簡單得多:

      //先序遍歷

      void PreOrder(BiTreebt) //bt為二叉樹或某一子樹根節(jié)點(diǎn)的指針

      {

      if(bt!=NULL) //如果bt為空,遞歸結(jié)束

      {

      visit(bt);//訪問根節(jié)點(diǎn)

      PreOrder(bt->lchild); //先序遍歷左子樹

      PreOrder(bt->rchild); //先序遍歷右子樹

      }

      }

      //中序遍歷

      void InOrder(BiTreebt) //bt為二叉樹或某一子樹根節(jié)點(diǎn)的指針

      {

      if(bt!=NULL) //如果bt為空,遞歸結(jié)束

      {

      InOrder(bt->lchild); //先序遍歷左子樹

      visit(bt);//訪問根節(jié)點(diǎn)

      InOrder(bt->rchild); //先序遍歷右子樹

      }

      }

      //后序遍歷

      void PostOrder(BiTreebt) //bt為二叉樹或某一子樹根節(jié)點(diǎn)的指針

      {

      if(bt!=NULL) //如果bt為空,遞歸結(jié)束

      {

      PostOrder(bt->lchild); //先序遍歷左子樹

      PostOrder(bt->rchild); //先序遍歷右子樹

      visit(bt);//訪問根節(jié)點(diǎn)

      }

      }

      由此可見,采用遞歸方式,三種遍歷算法的區(qū)別只在于訪問根節(jié)點(diǎn)語句的位置不同,相比非遞歸算法要簡單很多。

      4結(jié)論

      在C語言教學(xué)中,遞歸函數(shù)的設(shè)計(jì)一直是其中的重點(diǎn)和難點(diǎn),本文首選分析了采用遞歸算法解決問題的基本條件,然后列舉了幾個(gè)比較經(jīng)典的案例,對其進(jìn)行分析執(zhí)行,使學(xué)生能正確掌握遞歸函數(shù)的設(shè)計(jì)。

      參考文獻(xiàn):

      [1]潭浩強(qiáng).C語言程序設(shè)計(jì)[M].北京:清華大學(xué)出版社,2017.

      [2]樊艷芬,周琪云,吳帥.用Java語言實(shí)現(xiàn)八皇后問題的遞歸和非遞歸算法設(shè)計(jì)[J].計(jì)算機(jī)與現(xiàn)代化,2007(3).

      [3]嚴(yán)蔚敏.數(shù)據(jù)結(jié)構(gòu)[M].北京:清華大學(xué)出版社,2013.

      猜你喜歡
      案例分析C語言教學(xué)設(shè)計(jì)
      基于Visual Studio Code的C語言程序設(shè)計(jì)實(shí)踐教學(xué)探索
      基于C語言的計(jì)算機(jī)軟件編程
      高職高專院校C語言程序設(shè)計(jì)教學(xué)改革探索
      父親缺失案例分析
      冷庫建筑火災(zāi)特點(diǎn)及調(diào)查方法研究
      高中數(shù)學(xué)一元二次含參不等式的解法探討
      “仿真物理實(shí)驗(yàn)室” 在微課制作中的應(yīng)用
      翻轉(zhuǎn)課堂在高職公共英語教學(xué)中的應(yīng)用現(xiàn)狀分析及改善建議
      讓語文課堂評價(jià)語綻放異彩
      論子函數(shù)在C語言數(shù)據(jù)格式輸出中的應(yīng)用
      治多县| 修文县| 新郑市| 枣庄市| 尼玛县| 衡南县| 玉溪市| 大兴区| 达拉特旗| 航空| 合阳县| 武清区| 麻阳| 汤阴县| 大连市| 新密市| 鹿泉市| 大港区| 澄江县| 马鞍山市| 青冈县| 岳普湖县| 承德市| 武山县| 揭阳市| 邛崃市| 鹤壁市| 西乡县| 涪陵区| 吉安市| 枞阳县| 大方县| 阜平县| 武宁县| 扎赉特旗| 拜城县| 闽侯县| 汉源县| 五常市| 观塘区| 新津县|