1、遞迴:(歸去來兮)
遞迴效率較低,如果明確知道迭代次數,則能用迭代最好用迭代,遞迴是函式自己呼叫自身,每次呼叫都需要入棧等操作。但是遞迴操作要比迭代簡單和清楚。
遞迴函式的優點是定義簡單,邏輯清晰。理論上,所有的遞迴函式都可以寫成迴圈的方式,但迴圈的邏輯不如遞迴清晰。
使用遞迴函式需要注意防止棧溢位。在計算機中,函式呼叫是通過棧(stack)這種資料結構實現的,每當進入乙個函式呼叫,棧就會加一層棧幀,每當函式返回,棧就會減一層棧幀。由於棧的大小不是無限的,所以,遞迴呼叫的次數過多,會導致棧溢位。
解決遞迴呼叫棧溢位的方法是通過尾遞迴優化,事實上尾遞迴和迴圈的效果是一樣的,所以,把迴圈看成是一種特殊的尾遞迴函式也是可以的。
尾遞迴是指,在函式返回的時候,呼叫自身本身,並且,return語句不能包含表示式。這樣,編譯器或者直譯器就可以把尾遞迴做優化,使遞迴本身無論呼叫多少次,都只占用乙個棧幀,不會出現棧溢位的情況。
尾遞迴呼叫時,如果做了優化,棧不會增長,因此,無論多少次呼叫也不會導致棧溢位。
遺憾的是,大多數程式語言沒有針對尾遞迴做優化。
遞迴需要遵守的重要規則:
1)執行乙個方法時,就建立乙個新的受保護的獨立空間(棧空間);
2)方法的區域性變數是獨立的,不會相互影響;
3)如果方法中使用的是引用型別變數(比如陣列),就會共享該引用型別的資料;
4)遞迴必須向退出遞迴的條件逼近,否則就會是無限遞迴(導致棧溢位);
5)當乙個方法執行完畢,或者遇到return,就會返回,遵守誰呼叫,就將結果返回給誰,同時當方法執行完畢或者返回時,該方法也就執行完畢。
遞迴用於解決什麼樣的問題:
1)各種數學問題:8皇后問題,漢諾塔,階乘問題,迷宮問題,球和籃子問題等;(回溯,如果不能則會返回繼續尋找)
2)各種演算法中,例如快速排序,歸併排序,二分查詢,分治演算法等;
3)將用棧解決的問題,利用遞迴**會更加簡潔。
2、斐波那契數列的遞迴實現
1)遞迴定義至少有乙個終止條件,函式不再呼叫自身,開始返回。
2)遞迴和迭代的區別:迭代使用的是迴圈結構,遞迴使用的是選擇結構。但大量的遞迴呼叫會建立函式的副本,會消耗大量的時間和記憶體,而迭代不需要這種付出。
3)遞迴函式分為呼叫階段和回退階段,遞迴的回退順序是它呼叫順序的逆序。
舉例:列印輸入字元的倒序輸出:
3、分治思想
採取各個擊破,分而治之的原則。當乙個問題規模較大且不容易求解時,可以考慮將其分為幾個小的模組,逐一解決。採用分治思想處理問題時,其各個小模組通常具有與大問題相同的結構。
4、折半查詢
折半查詢法,是一種常用的查詢方法,該方法通過不斷縮小一半查詢的範圍,直到達到目的,所以效率比較高
前提:針對有序陣列(元素從小到大或從大到小),優點是查詢速度比較快,時間複雜度為o(log2n)。
迭代實現:
int遞迴實現main()
;
intleft, mid, right,num;
left = 0
; right = 10
; num = 27
;
while (left <=right)
printf(
"index:%d
", mid);
system(
"pause");
return0;
}
int binary_search(int arr, int left, int right,int上面講的遞迴的二分查詢法就是乙個分治演算法的典型例子,分治演算法常常是乙個方法,在這個方法中含有兩個對自身的遞迴呼叫,分別對應於問題的兩個部分。ele)
else
}int
main()
;
intleft, right, num, index;
left = 0
; right = 10
; num = 27
; index =binary_search(a, left, right, num);
printf(
"index:%d
", index);
system(
"pause");
return0;
}
二分查詢中,將查詢範圍分成比查詢值大的一部分和比查詢值小的一部分,每次遞迴呼叫只會有乙個部分執行。
折半查詢 分治法
include 分治策略 設a low.high 是當前的查詢區間,首先確定該區間的中點位置mid low high 2 然後將待查的k值與 a mid key比較 1.若k a mid 則查詢成功並返回該元素的物理下標 2.若ka mid 則要查詢的k必定位於右子表a mid 1.high 中,即...
遞迴和分治思想及其應用
更多 如果可以使用迭代,盡量別使用遞迴。由編譯原理可以知道,每次自呼叫的時候,計算機都需要儲存在呼叫,浪費時間空間。當然,迭代是當我們知道迴圈次數的時候。而當我們不知道迴圈次數,比如說對於資料夾和檔案進行遍歷,不知道深度的情況下,我們就需要遞迴來實現。顯然,遞迴是先解決小的問題,這種思想是分治思想。...
遞迴和分治思想及其應用
目錄 更多 如果可以使用迭代,盡量別使用遞迴。由編譯原理可以知道,每次自呼叫的時候,計算機都需要儲存在呼叫,浪費時間空間。當然,迭代是當我們知道迴圈次數的時候。而當我們不知道迴圈次數,比如說對於資料夾和檔案進行遍歷,不知道深度的情況下,我們就需要遞迴來實現。顯然,遞迴是先解決小的問題,這種思想是分治...