遞迴與goto (轉)

gugu99發表於2007-12-04
遞迴與goto (轉)[@more@]

遞迴與goto:namespace prefix = o ns = "urn:schemas--com::office" />

      written by leezy_2000

 

記得剛開始學習C時,老師和教材都有明訓:“千萬不要亂用goto語句,否則將導致可讀性極度下降。但能夠極大提高地情況,可以考慮使用。”抱著不求有功,但求無過地心思,goto一度被我扔到了垃圾簍。後來隨著閱讀程式碼量地增加,我發現goto至少在兩個方面可起到改善程式地作用。一是出錯處理,二是用來模仿遞迴。用來做出錯處理,在某些特定的場合可以,增強閱讀性。用來模擬遞迴,可以極大的提高程式的,但無疑會降低程式的可讀性。這篇文章討論後者。

我們來看一段程式碼:

 

求n—0範圍內,所有整數的累加。

unsigned add( unsigned num)

{

 

  if(num != 0) return num+add(num-1);

  else return 0;

}

使用的時候有:

unsigned c=100;

 

cout<< add(c) <

這段程式簡單的很,就是用遞迴求解,沒什麼好說。當然效率不會高,尤其num比較大的時候。這種影響是由於過於頻繁的導致的。

 

現在我們來歸納一下這次遞迴呼叫的特徵:

 

1.  由於遞迴函式原型一致,所以堆疊中存放的資料型別一致。也就是相當於一個陣列。

 

2.  先壓棧,增長堆疊大小,達到某個臨界條件,開始出棧。並對出棧資料進行累加。出棧的次數當然同壓棧的次數一致。

 

為了降低函式呼叫對效能的影響,我們來模擬這個過程。看如下程式和註釋。

 

  unsigned stack[100];//模擬堆疊,假設n為100

bool goback=false; //臨界條件

  int i=0; //計數

  int p=c; //p=100

  int num=0; //和

 

  //相當於遞迴函式的入口

  recurse:

  if( p!=0)//進棧

  {

    stack[i++] = p--;

 

    goto recurse;

  }

  else goback=true; //達到臨界條件了

 

  //出棧,求和,從遞迴中返回

  if( --i >=0 )

  {

    num +=stack[i];

    goto recurse;

  }

 

  這樣實現,在空間和時間上都會有較佳的改善,當然前提是要用在恰當的地方。

 

  最後說明一下,這個方法不是我發明的。Microsoft C/C++執行時庫中的qsort就是用這種辦法實現的。

 


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10748419/viewspace-987763/,如需轉載,請註明出處,否則將追究法律責任。

相關文章