2013-04-10 63 views
1

我想寫一個函數來通過遞歸來打印數組。在C++中通過遞歸打印數組

我寫了三個函數,但它們在原理上似乎是一樣的。

void printArray0(int theArray[], int theSize, int theIndex = 0) 
{ 
    cout << theArray[theIndex] << ' '; 
    if (++theIndex != theSize) printArray0(theArray, theSize, theIndex); 
    else cout << endl; 
} 

void printArray1(int theArray[], int theElementLeft) 
{ 
    cout << *theArray << ' '; 
    if (theElementLeft != 1) printArray1(theArray+1, theElementLeft-1); 
    else cout << endl; 
} 

void printArray2(int theArray[], int theSize) 
{ 
    static int myIndex = 0; 
    cout << theArray[myIndex] << ' '; 
    if (++myIndex != theSize) printArray2(theArray, theSize); 
    else cout << endl; 
} 

那麼它們之間是否存在顯着差異?

如果有,哪個功能最快,哪個最安全?

我希望能夠從別人的經驗:)

+1

我從來沒有過這樣的經歷:) – neagoegab 2013-04-10 14:21:02

+0

誰知道陰影中潛伏着什麼代碼?只有探查者知道! – 2013-04-10 14:21:07

+1

當給定的大小爲0時,所有三個都將失敗。 – interjay 2013-04-10 14:21:33

回答

4

第三個不等於前兩個,因爲它使用一個靜態變量來保持當前狀態。這是一件壞事(想象一下從多個線程同時運行這個函數來查看原因)。這甚至可以起作用的原因是每次函數調用都不會有多次遞歸調用。例如,試圖在一個二叉樹的遞歸遍歷中保持一個靜態狀態將會非常悲慘地失敗。這就是爲什麼當前狀態應該通過參數傳遞給遞歸函數,而不使用靜態或成員上下文。

前兩個版本之間應該沒有性能差異,因爲它們的時間將受數據輸出的支配。

我會改變的第二功能的簽名是這樣

void printArray1(int *theArray, int theElementLeft) 

,因爲你從來沒有使用theArray作爲數組,只能作爲一個指針。從技術上講,這並不重要,因爲無論如何,數組「衰減」指針,但我認爲這會稍微提高可讀性。

3

功能學會0和1是同樣安全。

函數2在多線程環境中不安全,因爲它使用了一個靜態變量。此外,連續調用此函數將在最後一次調用「關閉」的位置開始,因爲myIndex從未重新初始化爲零。


個人而言,我更喜歡的功能1風格切換功能0 0功能在其使用前遞增(if (++theIndex != theSize)),這是一個聰明的聰明,在我看來,將阻礙未來的維護。有副作用的情況是我建議你避免的。

1

它們都沒有多大意義,沒有任何人會爲此使用遞歸的理由。第一個版本可能是最不好的,因爲它是最容易閱讀的。

static版本是最危險的,因爲它不是線程安全的。而使用靜態使整個遞歸(更多)毫無意義。

一般來說,遞歸有意義的情況很少,這不是其中之一。所有三個版本都是危險的,因爲如果參數不正確,則不能保證遞歸會停止。所有這三個版本都會比普通循環消耗更多的RAM內存,並且它們會執行得更慢,同時也使得程序的可讀性大大降低。你的程序容易受到堆棧溢出的影響。

編譯器通常不會有效地優化遞歸。無論它們是否可以取決於您是否使用「尾遞歸」。

作爲便箋,您的編碼&縮進樣式是不可讀和不安全的。按照if/else對每行使用一個新行,並且對每個if/else語句始終使用{}

+2

(作爲一個經驗法則,使用遞歸唯一有意義的情況是使用遞歸有意義的情況。) – Lundin 2013-04-10 14:34:25

+0

什麼時候應該使用遞歸?我剛剛發現許多算法演示使用遞歸,所以我試圖練習:( – redcap 2013-04-10 14:39:24

+0

@redcap更嚴重的說明,唯一有意義的情況是當你在進行二分搜索,二進制(「合併」)排序,二叉樹插入/搜索和類似的,這些情況下,遞歸可能會使算法更具可讀性,這是唯一應該使用它的地方。遞歸可以被展開成一個普通的循環,但該循環不一定更具可讀性。 – Lundin 2013-04-11 13:08:57