阿摩線上測驗 登入

申論題資訊

試卷:104年 - 104 身心障礙特種考試_三等_資訊處理:程式語言#24069
科目:程式語言
年份:104年
排序:0

申論題內容

三、為何尾遞迴(tail recursion)通常比一般性的遞迴執行上更有效率?請說明之。請以 熟悉的程式語言寫出一段使用尾遞迴技巧的程式碼例子。(20 分)

詳解 (共 2 筆)

詳解 提供者:114年高考上榜

尾遞迴(tail recursion)是指一個函數在調用自身之後不做任何操作就直接返回,這種遞迴方式可以被編譯器優化為迴圈,從而大大提高遞迴的效率。一般性的遞迴在調用自身之後需要保存當前的函數上下文,而這些上下文的保存需要額外的記憶體空間和時間成本,因此效率相對較低。

 
以下是一段使用尾遞迴技巧的JavaScript程式碼例子,該程式碼實現了計算一個正整數的階乘的功能:
 
 
function factorial(n, acc = 1) {
  if (n === 0) {
    return acc;
  } else {
    return factorial(n - 1, acc * n);
  }
}
 
// 計算5的階乘
console.log(factorial(5)); // 120
在這個例子中,函數factorial使用了一個額外的參數acc來保存計算結果,如果n等於0,則直接返回acc;否則,將計算結果acc乘以n作為新的acc值,同時將n-1作為新的參數遞迴調用函數本身。這樣可以使得遞迴在每次調用自身之後直接返回,不需要保留任何的函數上下文,因此可以避免額外的記憶體開銷,提高遞迴的效率。
詳解 提供者:hchungw
尾遞迴(Tail Recursion)是遞迴的一種特殊形式,其中遞迴呼叫是函式的最後一個操作。這意味著,在尾遞迴中,遞迴函式的返回值直接被傳遞回其上一層呼叫,不需要在返回值後進行額外的計算。
為什麼尾遞迴更有效率?
尾遞迴比一般遞迴更有效率的原因主要在於它可以被編譯器或解譯器優化,稱為尾遞迴優化(Tail Call Optimization, TCO)。這種優化可以將尾遞迴轉換為迴圈,從而節省了額外的堆疊空間,避免了過多的函式呼叫層級。
堆疊空間節省:一般遞迴需要為每次呼叫分配新的堆疊幀,而尾遞迴可以重用當前的堆疊幀,因為沒有其他操作需要在遞迴呼叫返回後執行。
避免堆疊溢出:由於尾遞迴使用固定數量的堆疊幀,可以避免因為過深的遞迴導致的堆疊溢出(Stack Overflow)。
尾遞迴的程式碼例子
以下是使用尾遞迴來計算階乘的例子。這裡以 Python 作為範例語言。
python
複製程式碼
def tail_recursive_factorial(n, accumulator=1):
    if n == 0:
        return accumulator
    else:
        return tail_recursive_factorial(n - 1, n * accumulator)
# 呼叫尾遞迴函式
result = tail_recursive_factorial(5)
print(result)  # Output: 120
解釋
tail_recursive_factorial 函式:這個函式接收兩個參數,n 是要計算階乘的數字,accumulator 是累積器,用來保存中間結果。
基礎情況:如果 n 是 0,直接返回累積器的值(此時累積器已經包含最終結果)。
遞迴情況:如果 n 不是 0,將當前 n 和累積器相乘的結果傳遞給下一次呼叫,同時 n 減 1。
比較
這是一般遞迴計算階乘的方式:
python
複製程式碼
def recursive_factorial(n):
    if n == 0:
        return 1
    else:
        return n * recursive_factorial(n - 1)
# 呼叫一般遞迴函式
result = recursive_factorial(5)
print(result)  # Output: 120
在一般遞迴中,每次呼叫都會產生新的堆疊幀,直到遞迴回溯回來。而在尾遞迴中,因為沒有需要在遞迴返回後執行的操作,堆疊幀可以重用。
結論
尾遞迴通常比一般遞迴更有效率,因為它可以通過尾遞迴優化節省堆疊空間,避免過多的函式呼叫層級,從而提高執行效率。理解並應用尾遞迴可以寫出更高效、更具可讀性的遞迴程式碼。