網站首頁 編程語言 正文
1.學習目標
遞歸函數是直接調用自己或通過一系列語句間接調用自己的函數。遞歸在程序設計有著舉足輕重的作用,在很多情況下,借助遞歸可以優雅的解決問題。本節主要介紹遞歸的基本概念以及如何構建遞歸程序。
通過本節學習,應掌握以下內容:
理解遞歸的基本概念,了解遞歸背后蘊含的編程思想
掌握構建遞歸程序的方法
2.遞歸
2.1遞歸的基本概念
遞歸是一種解決問題的方法,它將問題不斷的分為更小的子問題,通過處理普通的子問題來解決問題。遞歸函數是直接調用自己或通過一系列語句間接調用自己的函數。需要注意的是,遞歸函數每次調用自己時,都會將原問題進行簡化,最終較小問題的序列必須收斂于基本情況,解決問題,終止遞歸。利用遞歸可以非常優雅的解決一些復雜問題。很多數學函數就是遞歸定義的,比如使用遞歸定義的階乘函數:
盡管這個定義是遞歸的,但它不是無限循環無法終止的。事實上,利用此函數可以非常簡單的計算階乘。例如計算3!,根據定義,有3!=3(3–1)!=3(2!),接下來我們需要解決2!,再次應用定義 3! = 4(2!) = 3[(2)(2?1)!] = 3(2)(1!),繼續此過程,最后我們需要計算0!,而根據定義0!=1,計算過程就結束了:
3!=3(2!)=3(2)(1!)=3(2)(1)(0!)=3(2)(1)(1)=6
可以看到,遞歸定義并非是無限循環的,因為每次應用定義,程序都會將問題分解為更簡單的子問題,在階乘函數示例中,即為計算較小數的階乘,直到計算0!,這不需要再次應用遞歸即可求解。當遞歸到底時,我們得到一個可以直接計算的閉合表達式,也被稱為遞歸的“基本情況”。而函數調用自身來執行子任務時,被稱為“遞歸情況”。
2.2遞歸的重要性
遞歸函數是從數學中借鑒的一種重要的編程技術,通常使用遞歸可以極大的降低代碼量,在許多可以分解為子問題的任務中非常有用,例如,排序、遍歷和搜索等通常可以借助遞歸方法快速的給出解決方案。
2.3遞歸三原則
和許多算法一樣,遞歸同樣有著需要遵守的重要原則,稱為遞歸三原則:
- 遞歸算法必須有基本情況
- 遞歸算法必須改變狀態并逐漸收斂于基本情況
- 遞歸算法必須包含遞歸情況,能夠遞歸的調用自身
需要注意的是,遞歸的核心思想并不是循環,而是將問題分解成更小、更容易解決的子問題。
2.4遞歸的應用
遞歸在程序設計中有著十分重要的作用,以下是一些常用到遞歸的實際場景:
- 斐波那契數列、階乘計算等數學問題
- 歸并排序、快速排序
- 二分查找
- 樹和圖的遍歷以及相關問題
- 漢諾塔
3.遞歸示例
本節中,我們將從簡單的列表求和問題入手,了解遞歸算法的使用方式,然后再了解如何解決經典遞歸問題——漢諾塔。
3.1列表求和
列表求和是十分簡單的問題,用來了解遞歸算法的思想再合適不過了。例如我們需要計算列表 [1, 2, 3, 4, 5] 的和,如果利用循環函數計算,則可以編寫如下代碼計算列表中所有數之和:
def sum_list(list_data):
result = 0
for i in range(list_data):
result += i
return result
如果不使用循環,我們該如何解決這一問題呢?我們可以寫出求和過程((((1+2)+3)+4)+5),而根據加法交換律,計算過程也可以寫為(1+(2+(3+(4+5)))),這時我們就可以很清楚的看到,列表的數據總和等于列表第一個元素加上其余元素:
使用 python 實現以上等式如下:
def sum_list(list_data):
if len(num_list) == 1:
return list_data[0]
else:
return list_data[0] + sum_list(list_data[1:])
在代碼中,首先給出了函數退出的條件,這就是遞歸函數的基本情況,在示例中就是說,長度為 1 的列表,其元素和就是列表中的數。不滿足退出條件,sum_list 則會調用自己,這就是遞歸函數的遞歸情況,也是其稱為遞歸函數的原因。
在下圖(a)中,可以看到求解 [1, 2, 3, 4, 5] 時的遞歸調用過程,每次遞歸調用都是在解決一個更接近基本情況的問題,直到問題不能被進一步簡化。
當問題無法簡化時,開始拼接所有子問題的解,下圖(b)展示遞歸函數 sum_list 在返回一系列調用結果時所進行的加法操作,當返回到頂層時,就解決了最初的問題。
3.2漢諾塔(Towers of Hanoi)問題
漢諾塔(Towers of Hanoi)是一道十分經典的謎題。它由三個塔和許多不同尺寸的圓盤組成,這些圓盤可以移動到任何桿上。開始時圓盤按尺寸升序排列在一個塔上,頂部的圓盤最小,底部圓盤最大。謎題的目標是將疊好的圓盤移動到另一個桿,且滿足以下規則:
- 一次只能移動一個圓盤
- 較大圓盤不能放在較小的圓盤上
接下來我們講解如何借助一根中間塔 Auxiliary,將高度為 n 的一疊圓盤從起始塔 Source 移到終點塔 Destination:
- 借助終點塔 Destination,將頂部的 n - 1 個圓盤從 Source 移動到 Auxiliary
- 將第 n 個圓盤從 Source 塔移動到終點塔 Destination
- 借助 Source 塔,將 n - 1 個磁盤從輔助塔 Auxiliary 移動到終點塔 Destination
只要遵循漢諾塔的移動規則,就可以遞歸地執行上述步驟。最簡單的漢諾塔是只有一個盤子,在這種情況下,只需將這個盤子移到終點柱子 Destination 即可,這就是基本情況。上述遞歸步驟通過逐漸減小高度 n 來向基本情況靠近,如下圖所示:
算法的關鍵在于進行兩次遞歸調用,第一次遞歸是將除了最后一個圓盤以外的其他所有圓盤從 Source 塔移到輔助塔 Auxiliary 。然后將最后一個圓盤移到終點塔 Destination。第二次遞歸是將圓盤從 Auxiliary 移到 Destination:
def towersOfHanoi(number, source=1, destination=3, auxiliary=2):
if number >= 1:
towersOfHanoi (number - 1, source, auxiliary, destination)
print("Move disk %d from tower %d to tower %d" % (number, source, destination))
towersOfHanoi (number - 1, auxiliary, destination, source)
towersOfHanoi(number=3)
程序輸出如下所示:
Move disk 1 from tower 1 to tower 3
Move disk 2 from tower 1 to tower 2
Move disk 1 from tower 3 to tower 2
Move disk 3 from tower 1 to tower 3
Move disk 1 from tower 2 to tower 1
Move disk 2 from tower 2 to tower 3
Move disk 1 from tower 1 to tower 3
原文鏈接:https://blog.csdn.net/LOVEmy134611/article/details/121197208
相關推薦
- 2022-06-25 Docker?安裝?Consul單機模式的操作方法_docker
- 2024-02-29 UNI-APP頁面通訊、組件子向父、父向子傳遞數據
- 2021-11-02 Linux環境下生成openssl證書注意細節介紹_Linux
- 2022-12-23 Kotlin標準函數與靜態方法基礎知識詳解_Android
- 2022-05-05 R語言因子類型的實現_R語言
- 2022-10-15 script 標簽 async 屬性
- 2024-01-14 “xxx“ is not an enclosing class 解決辦法
- 2022-12-03 pytorch模型保存與加載中的一些問題實戰記錄_python
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支