導航:首頁 > 源碼編譯 > 遞歸演算法過程

遞歸演算法過程

發布時間:2023-01-05 08:24:05

1. 什麼是遞歸演算法

遞歸演算法就是一個函數通過不斷對自己的調用而求得最終結果的一種思維巧妙但是開銷很大的演算法。
比如:
漢諾塔的遞歸演算法:
void move(char x,char y){
printf("%c-->%c\n",x,y);
}

void hanoi(int n,char one,char two,char three){
/*將n個盤從one座藉助two座,移到three座*/
if(n==1) move(one,three);
else{
hanoi(n-1,one,three,two);
move(one,three);
hanoi(n-1,two,one,three);
}
}

main(){
int n;
printf("input the number of diskes:");
scanf("%d",&n);
printf("The step to moving %3d diskes:\n",n);
hanoi(n,'A','B','C');
}
我說下遞歸的理解方法
首先:對於遞歸這一類函數,你不要糾結於他是干什麼的,只要知道他的一個模糊功能是什麼就行,等於把他想像成一個能實現某項功能的黑盒子,而不去管它的內部操作先,好,我們來看下漢諾塔是怎麼樣解決的
首先按我上面說的把遞歸函數想像成某個功能的黑盒子,void hanoi(int n,char one,char two,char three); 這個遞歸函數的功能是:能將n個由小到大放置的小長方形從one 位置,經過two位置 移動到three位置。那麼你的主程序要解決的問題是要將m個的"漢諾塊"由A藉助B移動到C,根據我們上面說的漢諾塔的功能,我相信傻子也知道在主函數中寫道:hanoi(m,A,B,C)就能實現將m個塊由A藉助B碼放到C,對吧?所以,mian函數裡面有hanoi(m,'A','C','B');這個調用。
接下來我們看看要實現hannoi的這個功能,hannoi函數應該幹些什麼?
在hannoi函數里有這么三行
hanoi(n-1,one,three,two);
move(one,three);
hanoi(n-1,two,one,three);
同樣以黑盒子的思想看待他,要想把n個塊由A經過B搬到C去,是不是可以分為上面三步呢?
這三部是:第一步將除了最後最長的那一塊以外的n-1塊由one位置經由three搬到two 也就是從A由C搬到B 然後把最下面最長那一塊用move函數把他從A直接搬到C 完事後 第三步再次將剛剛的n-1塊藉助hannoi函數的功能從B由A搬回到C 這樣的三步實習了n塊由A經過B到C這樣一個功能,同樣你不用糾結於hanoi函數到底如何實現這個功能的,只要知道他有這么一個神奇的功能就行
最後:遞歸都有收尾的時候對吧,收尾就是當只有一塊的時候漢諾塔怎麼個玩法呢?很簡單吧,直接把那一塊有Amove到C我們就完成了,所以hanoni這個函數最後還要加上 if(n==1)move(one,three);(當只有一塊時,直接有Amove到C位置就行)這么一個條件就能實現hanoin函數n>=1時將n個塊由A經由B搬到C的完整功能了。
遞歸這個復雜的思想就是這樣簡單解決的,呵呵 不知道你看懂沒?純手打,希望能幫你理解遞歸
總結起來就是不要管遞歸的具體實現細節步驟,只要知道他的功能是什麼,然後利用他自己的功能通過調用他自己去解決自己的功能(好繞口啊,日)最後加上一個極限情況的條件即可,比如上面說的1個的情況。

2. 一個遞歸演算法必須包括什麼

遞歸演算法包含的兩個部分:

1、由其自身定義的與原始問題類似的更小規模的子問題(只有數據規模不同),它使遞歸過程持續進行,稱為一般條件。

2、所描述問題的最簡單的情況,它是一個能控制遞歸過程結束的條件,稱為基本條件。(遞歸出口)

遞歸的定義:

如果一個對象部分地由它自身組成或按它自己定義,則稱它是遞歸的,所以說遞歸就是函數/過程/子過程在運行過程中直接或間接調用自身而產生的重入現象。

遞歸的基本思想:

就是把一個規模大的問題分為若干個規模較小的子問題求解,而每一個子問題又可以分為幾個規模更小的子問題。基本上,所有的遞歸問題都可以用遞推公式來表示。

最重要的一點就是假設子問題已經解決了,現在要基於已經解決的子問題來解決當前問題;或者說,必須先解決子問題,再基於子問題來解決當前問題或者可以這么理解:遞歸解決的是有依賴順序關系的多個問題。

遞歸的優缺點:

優點:邏輯清楚,結構清晰,可讀性好,代碼簡潔,效率高(拓展:DFS深度優先搜素,前中後序二叉樹遍歷)

缺點:函數調用開銷大,空間復雜度高,有堆棧溢出的風險

3. 遞歸演算法 求詳細過程

遞歸演算法是把問題轉化為規模縮小了的同類問題的子問題。然後遞歸調用函數(或過程)來表示問題的解。
遞歸演算法解決問題的特點:
(1) 遞歸就是在過程或函數里調用自身。
(2) 在使用遞歸策略時,必須有一個明確的遞歸結束條件,稱為遞歸出口。
(3) 遞歸演算法解題通常顯得很簡潔,但遞歸演算法解題的運行效率較低。所以一般不提倡用遞歸演算法設計程序。
(4) 在遞歸調用的過程當中系統為每一層的返回點、局部量等開辟了棧來存儲。遞歸次數過多容易造成棧溢出等。所以一般不提倡用遞歸演算法設計程序。
遞歸演算法要求
遞歸演算法所體現的「重復」一般有三個要求:
一是每次調用在規模上都有所縮小(通常是減半);
二是相鄰兩次重復之間有緊密的聯系,前一次要為後一次做准備(通常前一次的輸出就作為後一次的輸入);
三是在問題的規模極小時必須用直接給出解答而不再進行遞歸調用,因而每次遞歸調用都是有條件的(以規模未達到直接解答的大小為條件),無條件遞歸調用將會成為死循環而不能正常結束。
舉例
描述:把一個整數按n(2<=n<=20)進製表示出來,並保存在給定字元串中。比如121用二進製表示得到結果為:「1111001」。
參數說明:s: 保存轉換後得到的結果。
n: 待轉換的整數。
b: n進制(2<=n<=20)
void
numbconv(char *s, int n, int b)
{
int len;
if(n == 0) {
strcpy(s, "");
return;
}
/* figure out first n-1 digits */
numbconv(s, n/b, b);
/* add last digit */
len = strlen(s);
s[len] = ""[n%b];
s[len+1] = '\0';
}
void
main(void)
{
char s[20];
int i, base;
FILE *fin, *fout;
fin = fopen("palsquare . in", "r");
fout = fopen("palsquare.out", "w");
assert(fin != NULL && fout != NULL);
fscanf(fin, "%d", &base);
/*PLS set START and END*/
for(i=START; i <= END; i++) {
numbconv(s, i*i, base);
fprintf(fout, "%s\n", s);
}
exit(0);
}
C#:例子
例:一列數的規則如下: 1、1、2、3、5、8、13、21、34...... 求第30位數是多少。
public class MainClass
{
public static void Main()
{
Console.WriteLine(Foo(30));
}
public static int Foo(int i)
{
if (i <= 0)
return 0;
else if(i > 0 && i <= 2)
return 1;
else return Foo(i -1) + Foo(i - 2);
}
}

4. 遞歸演算法是怎麼運行的

遞歸演算法是把問題轉化為規模縮小了的同類問題的子問題。然後遞歸調用函數(或過程)來表示問題的解。
一個過程(或函數)直接或間接調用自己本身,這種過程(或函數)叫遞歸過程(或函數)。
遞歸演算法
遞歸演算法流程
遞歸過程一般通過函數或子過程來實現。遞歸方法:在函數或子過程的內部,直接或者間接地調用自己的演算法。

演算法簡析
遞歸是計算機科學的一個重要概念,遞歸的方法是程序設計中有效的方,採用遞歸編寫
遞歸能使程序變得簡潔和清晰。

5. 漢諾塔遞歸演算法是什麼

hanot (n-1,b,a,c);(解釋:在把B塔上的(n-1))個藉助A塔移動到C塔)

為了實現 n個盤從 藉助c 從a 移動到 b

思路如下:

首先考慮極限當只有一個盤的時候,盤直接從 a -> b即可。

當有2個盤的時候,把1號盤從a -> c 然後 把2號盤 a->b 再 把 2好盤從 c - > b。

當有n個盤的時候,把 n-1個 盤 藉助 b 移動到 c 然後將 n號盤從 a -> b。

這時候只要將 n-1想辦法從c移動到 b 藉助 a 那麼就可以先把 n-2個盤藉助b移動到a。

遞歸,就是在運行的過程中調用自己。

構成遞歸需具備的條件:

1,子問題須與原始問題為同樣的事,且更為簡單;

2,不能無限制地調用本身,須有個出口,化簡為非遞歸狀況處理。

在數學和計算機科學中,遞歸指由一種(或多種)簡單的基本情況定義的一類對象或方法,並規定其他所有情況都能被還原為其基本情況。

以上內容參考:網路-遞歸公式

6. 六、遞歸與回溯演算法

在計算機領域裡面,很多問題都可以要採用遞歸演算法來解決。遞歸中,最長用到的方法就是回溯法。我們具體分析問題的時候,可以發現這類問題本質是一個樹的形狀。

遞歸演算法的本質還是將原來的問題轉化為了更小的同一問題,進行解決。一般注意兩點:
1、遞歸終止的條件。對應到了遞歸演算法中最基本的問題,也是最最簡單的問題。
2、遞歸過程。遞歸過程需要將原問題一步一步的推到更小的 同一 問題,更小的意思就是子問題解決起來就更加的簡單。有寫情況是能夠找到一個遞推的公式的。這個過程中就需要透徹的去理解遞歸函數的意義。明確這個函數的輸入和輸出是什麼,這樣來寫的話,就清晰多了。

因為有了這樣的遞歸公式,那麼我們就很容易的能看出來遞歸的終止條件就是我們知道的f(0)和f(1)了。有了f(0)和f(1)之後,我們就能夠繼續的遞推出f(3)一直到f(n)了。

但是我們現在才用一個遞歸演算法的思想來解決這個問題:

像我們常見的數據結構如鏈表、樹、圖等都是有著天然的遞歸結構的,鏈表由於是一個線性的結構,那麼通常我們也是能夠直接循環遍歷就能解決問題的,但是這里我們用遞歸法來解決一下LeetCode上面的問題
LeetCode 203 移除鏈表元素
分析:鏈表的結構可以理解成一個節點連接這一個更短的鏈表,這樣依次一直看下去,直到最後一個節點None,那麼我們這個時候的遞歸終止條件就是head指向None了,返回的就是None

深入的理解遞歸演算法之後,我們就開始進行回溯法的學習。通過LeetCode上面的幾道題,我們來深入的探討一下遞歸與回溯法的應用。

持續更新中...
數據結構與演算法系列博客:
一、數據結構與演算法概述
二、數組及LeetCode典型題目分析
三、鏈表(Linked list)以及LeetCode題
四、棧與隊列(Stack and Queue
五、樹(Trees)
六、遞歸與回溯演算法
七、動態規劃
八、排序與搜索
九、哈希表

參考資料
1、
2、
3、

7. 遞歸演算法的執行過程,一般來說,可先後分成哪兩個階段

遞歸演算法的執行過程,一般來說,可先後分成「遞推」與「回歸」兩個階段。

8. 什麼是遞歸

程序調用自身就叫做遞歸。
遞歸一般用來算一些比較麻煩的演算法問題。
遞歸跟循環的區別,循環注重過程,而遞歸值注重結果。
簡單的來說就是:用循環能實現的,遞歸一般可以實現,但是能用遞歸實現的,循環不一定能。因為有些題目①只注重循環的結束條件和循環過程,而往往這個結束條件不易表達(也就是說用循環並不好寫);②只注重循環的次數而不注重循環的開始條件和結束條件(這個循環更加無從下手了)。
要想理解遞歸一時半會也弄不明白。但是寫遞歸需要記住三個步驟。
1.首先去找臨界值,即無需計算,獲得的值。
2. 找這一次和上一次的關系
3. 假設當前函數已經可以使用,調用自身計算上一次和這一次的關系。

9. java中遞歸演算法是怎麼算的

1.漢諾塔問題
import javax.swing.JOptionPane;
public class Hanoi {
private static final String DISK_B = "diskB";
private static final String DISK_C = "diskC";
private static final String DISK_A = "diskA";
static String from=DISK_A;
static String to=DISK_C;
static String mid=DISK_B;
public static void main(String[] args) {
String input=JOptionPane.showInputDialog("please input the number of the disks you want me move.");
int num=Integer.parseInt(input);
move(num,from,mid,to);
}
private static void move(int num, String from2, String mid2, String to2) {
if(num==1){
System.out.println("move disk 1 from "+from2+" to "+to2);
}
else {
move(num-1,from2,to2,mid2);
System.out.println("move disk "+num+" from "+from2+" to "+to2);
move(num-1,mid2,from2,to2);
}
}
}
2. 這是一個排列的例子,它所做的工作是將輸入的一個字元串中的所有元素進行排序並輸出,例如:你給出的參數是"abc" 則程序會輸出:
abc
acb
bac
bca
cab
cba
(1)演算法的出口在於:low=high也就是現在給出的排列元素只有一個時。
(2)演算法的逼近過程:先確定排列的第一位元素,也就是循環中i所代表的元素,
然後low+1開始減少排列元素,如此下去,直到low=high
public static void permute(String str) {
char[] strArray = str.toCharArray();
permute(strArray, 0, strArray.length - 1);
}
public static void permute(char[] list, int low, int high) {
int i;
if (low == high) {
String cout = "";
for (i = 0; i<= high; i++)
cout += list[i];
System.out.println(cout);
} else {
for (i = low; i<= high; i++) {
char temp = list[low];
list[low] = list[i];
list[i] = temp;
permute(list, low + 1, high);
temp = list[low];
list[low] = list[i];
list[i] = temp;
}
}
}
3。這是一個組合的例子,與上述的例子相似,只是它所做的工作是,輸出所給字元串中制定數目的元素的組合種類
(1)程序出口在於n=1,此時只要輸出目標數組的所有元素即可
(2)逼近過程,當n>1的時候,我們先取第一個元素放入目標數組中,然後n-1,如此下去,最後出來。
import javax.swing.JOptionPane;
public class Combination {
/**
* @param args
*/
public static void main(String[] args) {
String input = JOptionPane.showInputDialog("please input your String: ");
String numString = JOptionPane.showInputDialog("please input the number of your Combination: ");
int num = Integer.parseInt(numString);
Combine(input, num);
}
private static void Combine(String input, int num) {
char[] a = input.toCharArray();
String b = "";
Combine(a, num, b, 0, a.length);
}
private static void Combine(char[] a, int num, String b, int low, int high) {
if (num == 0) {
System.out.println(b);
} else {
for (int i = low; i<a.length; i++) {
b += a[i];
Combine(a, num - 1, b, i+1, a.length);
b=b.substring(0, b.length()-1);
}
}
}
}

閱讀全文

與遞歸演算法過程相關的資料

熱點內容
mac壓縮解壓視頻 瀏覽:904
這就是程序員魅力 瀏覽:294
京東java演算法筆試題 瀏覽:178
柱子加密箍筋不準有接頭 瀏覽:199
我的世界伺服器菜單插件如何使用 瀏覽:12
劉毅10000詞pdf 瀏覽:890
剛畢業的程序員會什麼 瀏覽:974
單片機控制64路開關量 瀏覽:982
win10截圖編程 瀏覽:420
怎樣把名字變成文件夾 瀏覽:203
文件怎麼搞成文件夾 瀏覽:730
多線程編程php 瀏覽:606
安卓機越用越卡有什麼辦法 瀏覽:17
高中生解壓操場適合做的游戲 瀏覽:395
程序員java招聘 瀏覽:462
未來之光手機雲伺服器 瀏覽:160
伺服器下載資料為什麼c盤滿了 瀏覽:265
怎麼清除空文件夾 瀏覽:544
如何查看派派伺服器 瀏覽:804
殺手6解壓畫面 瀏覽:671