程式設計風格的練習,遞迴

2021-10-06 23:30:26 字數 2880 閱讀 8261

本週的帖子將回到基礎知識,因為限制是使用遞迴 :

電腦科學中的遞迴是一種解決問題的方法,其中解決方案取決於對同一問題的較小例項(而不是迭代)的解決方案。 該方法可以應用於許多態別的問題,並且遞迴是電腦科學的中心思想之一。

—維基百科

遞迴((computer_science)

這是4在程式設計風格焦點series.other職位練習日交包括:

以程式設計風格介紹練習

以程式設計風格進行練習,將內容堆疊起來

程式設計風格的練習,kwisatz haderach風格

程式設計風格的練習,遞迴 (本文)

具有高階功能的程式設計風格的練習

以程式設計風格進行練習

以程式設計風格進行練習,回到物件導向的程式設計

程式設計風格的練習:地圖也是物件

程式設計風格的練習:事件驅動的程式設計

程式設計風格的練習和事件匯流排

反思程式設計風格的練習

面向方面的程式設計風格的練習

程式設計風格的練習:fp&i / o

關聯式資料庫風格的練習

程式設計風格的練習:電子**

併發程式設計風格的練習

使用hazelcast以程式設計風格進行練習

mapreduce樣式的練習

程式設計風格的練習總結

我已經在將函式式程式設計的方法應用於dijkstra演算法的上下文中寫過關於遞迴的文章。 讓我們詳細介紹其實現。 遞迴函式應提供兩個分支:

停止分支返回最終結果

乙個使用不同引數呼叫函式本身的分支

這是階乘函式的簡單實現:

fun

fact(n

:int

):int

return

result

}fact(5

)

在傳統的命令式程式設計中,函式使用區域性變數來累積臨時計算。 在遞迴函式中,這些變數被函式引數替換。

private

funrecursefact

(acc

:int,n

:int

):int=if

(n==1

)acc

(1)else

recursefact

(acc*n

,n-1

)(2)fun

fact(n

:int)=

recursefact(1

,n)(3)fact(5

)

停止分支

自呼分支

與以前的功能簽名相同

請注意,acc引數與命令示例中的result區域性變數具有相同的作用。

以下是練習中的功能。 它採用與階乘示例中所述完全相同的原理:

fun

words

(rest

:list

<

string

>,

stopwords

:list

<

string

>,

words

:list

<

string

>):

list

<

string

>

}

儘管遞迴**比命令**要簡潔得多,但是它遇到了乙個巨大的問題:函式呼叫被推入執行緒的呼叫堆疊中。 超出呼叫堆疊的大小時,將引發臭名昭著的stackoverflowerror

儘管可以在啟動時設定堆疊大小,但是它的大小是有限的。

用於管理堆疊大小的命令列選項-xss標準jvm熱點擊項-xx:threadstacksize專有選項如有更改,恕不另行通知
為了解決這個問題,kotlin(和scala)提供了乙個編譯器技巧:儘管源**是遞迴的,但是編譯後的位元組碼是通過標準迴圈實現的。 有兩個要求:

遞迴函式呼叫必須是最後乙個。

這稱為拖尾遞迴 。

修飾符tailrec必須新增到功能簽名中

上面的words()函式是尾遞迴的,因此新增tailrec關鍵字非常容易。 可以相應地對其進行更新,以使其永遠不會溢位。

相反,以下函式不是尾遞迴的,因為有兩個使用遞迴的呼叫。 因此, 位元組碼不能被優化。

fun

<

t>

quicksort

(list

:list

<

pair

int>>):

list

<

pair

int>>=if

(list

.size

<=1)

list

else

list

.random

().let

valabove

=filter

(list

,listof

())quicksort

(below

-pivot)+

pivot

+quicksort

(above

)}

通常,遞迴是一開始很難破解的。 但是,遷移**以使用遞迴很簡單:只需將區域性變數移動到累加器引數即可。 最難的部分是使遞迴函式尾遞迴以避免堆疊溢位。 有些功能允許,有些則不允許。

這篇文章的完整源**可以在github上找到。

翻譯自:

使用遞迴函式重寫程式設計練習8 程式設計風格的練習,遞迴

使用遞迴函式重寫程式設計練習8 本週的帖子將回到基礎知識,因為限制是使用遞迴 電腦科學中的遞迴是一種解決問題的方法,其中解決方案取決於對同一問題的較小例項 而不是迭代 的解決方案。該方法可以應用於多種型別的問題,而遞迴是電腦科學的中心思想之一。維基百科 遞迴 computer science 這是4...

程式設計風格的練習 事件驅動的程式設計

在兩周前的文章中,我們使用物件導向程式設計解決了問題 我們使用物件對問題空間進行建模。為了使物件與另乙個物件進行通訊,可以使用dispatch 方法。這是 程式設計風格練習 重點系列的第 9 個帖子。其他帖子包括 以程式設計風格介紹練習 以程式設計風格進行練習,將內容堆疊起來 程式設計風格的練習,k...

遞迴程式設計方法練習 遞迴輸出單鏈表

6 2 遞迴程式設計方法練習 遞迴輸出單鏈表 10 分 本題要求用遞迴方法編寫遞迴函式實現無頭結點單鏈表的輸出操作函式。l是乙個不帶頭結點的單鏈表,函式void listprint l rec linklist l 要求用遞迴的方法輸出無頭結點之單鏈表中各個元素的值,每個元素的前面都有乙個空格 包括...