1. 程式人生 > 其它 >資料結構和演算法:消除尾遞迴(Python)

資料結構和演算法:消除尾遞迴(Python)

遞迴是非常基本的演算法,雖然非常好用,但是也非常耗費空間資源,所以程式設計中在保證程式碼簡潔性和可讀性的前提下,如果可以不使用遞迴則儘量不使用遞迴。而尾遞迴則是一種可以在不使用其他輔助空間的情況下被消除的遞迴:如果一個函式的遞迴呼叫和呼叫的返回值總是在函式的末尾,且返回值不包括在表示式中,則這種遞迴通常稱之為尾遞迴。尾遞迴是可以通過迴圈來達到相同目的的,平常開發的時候如果沒有注意這種情況的話,很容易踩到這個坑。

尾遞迴示例

使用二分查詢演算法實現查詢一個列表中是否包含指定元素。

使用遞迴實現(尾遞迴):

def binary_search(data, item, low, high):
    mid = (low + high) // 2
    if low > high:
        return False
    elif item == data[mid]:
        return True
    elif item < data[mid]:
        return binary_search(data, item, low, mid - 1)
    else:
        return binary_search(data, item, mid + 1, high)

使用迴圈實現(消除尾遞迴):

def binary_search(data, item):
    low = 0
    high = len(data) - 1
    while low <= high:
        mid = (low + high) // 2
        if item == data[mid]:
            return True
        elif item < data[mid]:
            high = mid - 1
        else:
            low = mid + 1

    return False

注意,雖然遞迴呼叫的返回值在函式最後且返回了,但呼叫本身的返回值屬於表示式的一部分,那這種遞迴就不屬於尾遞迴了(雖然不屬於尾遞迴,如果可以不用遞迴實現,也可以考慮其他更好的方法)。

# 求一個正整數的階乘
def factorial(n):
    if n == 0:
        return 1
    else:
        return n * factorial(n - 1)