數據結構筆記淺記(一)

 

 

 

迭代:是一種重複執行某個任務的控制結構。在迭代中,程序會在滿足一定的條件下重複執行某 段代碼,直到這個條件不再滿足。

    以 for、while 爲代表

        總的來說,for 循環的代碼更加緊湊,while 循環更加靈活,兩者都可以實現迭代結構。選擇使用哪一個應該 根據特定問題的需求來決定。

 

遞歸:是一種算法策略,通過函數調用自身來解決問題。

        它主要包含兩個階段。

                1. 遞:程序不斷深入地調用自身,通常傳入更小或更簡化的參數,直到達到“終止條件”。

                 2. 歸:觸發“終止條件”後,程序從最深層的遞歸函數開始逐層返回,匯聚每一層的結果。

        而從實現的角度看,遞歸代碼主要包含三個要素。

                1. 終止條件:用於決定什麼時候由“遞”轉“歸”。

                2. 遞歸調用:對應“遞”,函數調用自身,通常輸入更小或更簡化的參數。

                3. 返回結果:對應“歸”,將當前遞歸層級的結果返回至上一層。

以求和爲例對比:對比普通遞歸和尾遞歸,兩者的求和操作的執行點是不同的。 ‧

普通遞歸:當函數返回到上一層級的函數後,需要繼續執行代碼,因此係統需要保存上一層調用的上下 文。 ‧

            求和操作是在“歸”的過程中執行的,每層返回後都要再執行一次求和操作。 ‧

尾遞歸:遞歸調用是函數返回前的最後一個操作,這意味着函數返回到上一層級後,無須繼續執行其他 操作,因此係統無須保存上一層函數的上下文。

            求和操作是在“遞”的過程中執行的,“歸”的過程只需層層返回。

 

小結:從計算角度看,迭代與遞歸可以得到相同的結果,但它們代表了兩種完全不同的思考和解決問題的範 式。 ‧ 迭代:“自下而上”地解決問題。從最基礎的步驟開始,然後不斷重複或累加這些步驟,直到任務完成。 ‧ 遞歸:“自上而下”地解決問題。將原問題分解爲更小的子問題,這些子問題和原問題具有相同的形式。

        1. 調用棧

                遞歸函數每次調用自身時,系統都會爲新開啓的函數分配內存,以存儲局部變量、調用地址和其他信息等。 這將導致兩方面的結果。 ‧ 函數的上下文數據都存儲在稱爲“棧幀空間”的內存區域中,直至函數返回後纔會被釋放。因此,遞歸 通常比迭代更加耗費內存空間。 ‧ 遞歸調用函數會產生額外的開銷。因此遞歸通常比循環的時間效率更低。

***:在實際中,編程語言允許的遞歸深度通常是有限的,過深的遞歸可能導致棧溢出錯誤。***

 

遞歸樹:以“斐波那契數列” 爲例。  給定一個斐波那契數列 0, 1, 1, 2, 3, 5, 8, 13, … ,求該數列的第 𝑛 個數字。 設斐波那契數列的第 𝑛 個數字爲 𝑓(𝑛) ,

即 𝑓(𝑛) = 𝑓(𝑛 − 1) + 𝑓(𝑛 − 2) 。

在函數內遞歸調用了兩個函數,這意味着從一個調用產生了兩個調用分支。最終將產生一棵層數爲 𝑛 的  遞歸樹。

        從本質上看,遞歸體現了“將問題分解爲更小子問題”的思維範式,這種分治策略至關重要。

                ‧ 從算法角度看,搜索、排序、回溯、分治、動態規劃等許多重要算法策略直接或間接地應用了這種思維 方式。

                ‧ 從數據結構角度看,遞歸天然適合處理鏈表、樹和圖的相關問題,因爲它們非常適合用分治思想進行分析。

 

迭代和遞歸使用場景:

    迭代:適用於簡單循環任務,代碼直觀、可讀性好

    遞歸:適用於子問題分解,如樹、圖、分治、回溯等,代碼結構簡潔、清晰

 

應該如何準確預估一段代碼的運行時間?

1. 確定運行平臺,包括硬件配置、編程語言、系統環境等,這些因素都會影響代碼的運行效率。

2. 評估各種計算操作所需的運行時間,例如加法操作 + 需要 1 ns ,乘法操作 * 需要 10 ns ,打印操作 print() 需要 5 ns 等。

3. 統計代碼中所有的計算操作,並將所有操作的執行時間求和,從而得到運行時間。    

 

時間複雜度分析統計的不是算法運行時間,而是算法運行時間隨着數據量變大時的增長趨勢。

 

相較於直接統計算法的運行時間,時間複雜度分析有哪些特點呢?

‧ 時間複雜度能夠有效評估算法效率。例如,算法 B 的運行時間呈線性增長,在 𝑛 > 1 時比算法 A 更慢, 在 𝑛 > 1000000 時比算法 C 更慢。事實上,只要輸入數據大小 𝑛 足夠大,複雜度爲“常數階”的算法 一定優於“線性階”的算法,這正是時間增長趨勢的含義。

‧ 時間複雜度的推算方法更簡便。顯然,運行平臺和計算操作類型都與算法運行時間的增長趨勢無關。因 此在時間複雜度分析中,我們可以簡單地將所有計算操作的執行時間視爲相同的“單位時間”,從而將 “計算操作運行時間統計”簡化爲“計算操作數量統計”,這樣一來估算難度就大大降低了。

‧ 時間複雜度也存在一定的侷限性。例如,儘管算法 A 和 C 的時間複雜度相同,但實際運行時間差別很 大。同樣,儘管算法 B 的時間複雜度比 C 高,但在輸入數據大小 𝑛 較小時,算法 B 明顯優於算法 C 。在 這些情況下,我們很難僅憑時間複雜度判斷算法效率的高低。當然,儘管存在上述問題,複雜度分析仍 然是評判算法效率最有效且常用的方法。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章