A. 漢諾塔遞歸演算法是什麼
漢諾塔(又稱河內塔)問題是源於印度一個古老傳說的益智玩具。大梵天創造世界的時候做了三根金剛石柱子,在一根柱子上從下往上按照大小順序摞著64片黃金圓盤。大梵天命令婆羅門把圓盤從下面開始按大小順序重新擺放在另一根柱子上。並且規定,在小圓盤上不能放大圓盤,在三根柱子之間一次只能移動一個圓盤。
我們在利用計算機求漢諾塔問題時,必不可少的一步是對整個實現求解進行演算法分析。到目前為止,求解漢諾塔問題最簡單的演算法還是同過遞歸來求。
這里還必須有一個結束點,或者具體的說是在調用到某一次後函數能返回一個確定的值,接著倒數第二個就能返回一個確定的值,一直到第一次調用的這個函數能返回一個確定的值。
現這個演算法可以簡單分為三個步驟:
(1) 把n-1個盤子由A 移到 B。
(2)把第n個盤子由 A移到 C。
(3) 把n-1個盤子由B 移到 C。
從這里入手,在加上上面數學問題解法的分析,我們不難發現,移到的步數必定為奇數步:
(1)中間的一步是把最大的一個盤子由A移到C上去。
(2)中間一步之上可以看成把A上n-1個盤子通過藉助輔助塔(C塔)移到了B上。
(3)中間一步之下可以看成把B上n-1個盤子通過藉助輔助塔(A塔)移到了C上。
B. 漢諾塔遞歸演算法是什麼
漢諾塔是經典遞歸問題:
相傳在古印度聖廟中,有一種被稱為漢諾塔(Hanoi)的游戲。該游戲是在一塊銅板裝置上,有三根桿(編號A、B、C),在A桿自下而上、由大到小按順序放置64個金盤。
游戲的目標:把A桿上的金盤全部移到C桿上,並仍保持原有順序疊好。操作規則:每次只能移動一個盤子,並且在移動過程中三根桿上都始終保持大盤在下,小盤在上,操作過程中盤子可以置於A、B、C任一桿上。
如果A只有一個(A->C)。
如果A有兩個(A->B),(A->C),(B->C)。
如果A有三個(A->C),(A->B),(C->B),(A->C),(B->A),(B->C),(A->C)。
如果更多,那麼將會爆炸式增長。
遞歸:就是函數自己調用自己。 子問題須與原始問題為同樣的事,或者更為簡單;遞歸通常可以簡單的處理子問題,但是不一定是最好的。
其實遞歸在某些場景的效率是很低下的。尤其是斐波那契.從圖你就可以發現一個簡單的操作有多次重復。因為它的遞歸調用倆個自己。那麼它的遞歸的膨脹率是指數級別的,重復了大量相同計算。
起源:
漢諾塔(又稱河內塔)問題是源於印度一個古老傳說的益智玩具。大梵天創造世界的時候做了三根金剛石柱子,在一根柱子上從下往上按照大小順序摞著64片黃金圓盤。
大梵天命令婆羅門把圓盤從下面開始按大小順序重新擺放在另一根柱子上。並且規定,在小圓盤上不能放大圓盤,在三根柱子之間一次只能移動一個圓盤。
C. 漢諾塔遞歸演算法是什麼
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,不能無限制地調用本身,須有個出口,化簡為非遞歸狀況處理。
在數學和計算機科學中,遞歸指由一種(或多種)簡單的基本情況定義的一類對象或方法,並規定其他所有情況都能被還原為其基本情況。
以上內容參考:網路-遞歸公式
D. java遞歸演算法的例子。
階乘:
要求:給定一個數值,計算出它的階乘值,例如5的階乘為5*4*3*2*1
實現:
[html] view plain
<span style="font-size:12px;"> // 利用遞歸實現一個數的階乘值 private static BigDecimal getNum(BigDecimal inNum) { if (inNum.compareTo(BigDecimal.ONE) == 0) { return inNum; } return inNum.multiply(getNum(inNum.subtract(BigDecimal.ONE))); }</span>
(2)Fibonacci數列:1,1,2,3,5,8,13……
要求:找出數列中指定index位置的數值
實現:
[html] view plain
<span style="font-size:12px;"> // 利用遞歸實現了Fibonacci數列 private static int fab(int index) { if (index == 1 || index == 2) { return 1; } else { return fab(index - 1) + fab(index - 2); } }</span>
(3)漢諾塔
要求:漢諾塔挪動
實現:
[html] view plain
<span style="font-size:12px;"> <span style="white-space:pre;"> </span>private static final String DISK_B = "diskB"; <span style="white-space:pre;"> </span>private static final String DISK_C = "diskC"; <span style="white-space:pre;"> </span>private static final String DISK_A = "diskA"; <span style="white-space:pre;"> </span>static String from=DISK_A; <span style="white-space:pre;"> </span> static String to=DISK_C; <span style="white-space:pre;"> </span> static String mid=DISK_B; <span style="white-space:pre;"> </span> public static void main(String[] args) { <span style="white-space:pre;"> </span> String input=JOptionPane.showInputDialog("please input the number of the disks you want me move."); <span style="white-space:pre;"> </span> int num=Integer.parseInt(input); <span style="white-space:pre;"> </span> move(num,from,mid,to); <span style="white-space:pre;"> </span> }</span>
[html] view plain
<span style="font-size:12px;"> // 利用遞歸實現漢諾塔 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); } }</span>
(4)排列組合
要求:將輸入的一個字元串中的所有元素進行排序並輸出,例如:你給出的參數是"abc",
則程序會輸出
abc
acb
bac
bca
cab
cba
實現:
[html] view plain
<span style="font-size:12px;"><span style="white-space:pre;"> </span>public static void permute(String str) { <span style="white-space:pre;"> </span> char[] strArray = str.toCharArray(); <span style="white-space:pre;"> </span> permute(strArray, 0, strArray.length - 1); <span style="white-space:pre;"> </span>}</span>
[html] view plain
<span style="font-size:12px;"> // 利用遞歸實現,將輸入的一個字元串中的所有元素進行排序並輸出 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];
E. 如何用java實現漢諾塔中的遞歸
public class Hannuota {
private int n;//儲存檔子個數
public Hannuota(int n){
this.n = n;
}
public void function(){
//初始化三個柱子,A是開始堆滿盤子的柱子,C是目標柱子
Pillar a = new Pillar(n,n,"A");
Pillar b = new Pillar(n,"B");
Pillar c = new Pillar(n,"C");
//把三個柱子按順序排好,詳見後面的演算法那裡的解釋
Pillar[] pillars = new Pillar[3];
pillars[0] = a;
if(n%2==0){
pillars[1] = b;
pillars[2] = c;
}else{
pillars[1] = c;
pillars[2] = b;
}
//開始移動,k用來計數,移動次數為2^n-1,至於為什麼,我不太清楚,
//反正有人證明過。i是用來保存最小那個盤子正在哪跟柱子上的。
int i=0;
for(int k=0;k<(int)Math.pow(2, n)-1;){
int min;
//將最小的盤子順時針移動一個柱子
min = pillars[i%3].Pop();
pillars[(i+1)%3].Push(min);
System.out.println(pillars[i%3]+"->"+pillars[(i+1)%3]);
k++;
i++;
//這個IF好像可以不要,當時寫的,後面忘了刪除。
if(k<(int)Math.pow(2, n)-1){
//如果,剩下兩根柱子中,某一根為空,則一定是非空那根中最上面個盤子
//移動到空的那個柱子上。若兩根都不為空,則把編號小的一個盤子
//移動到另外跟柱子上
if(!pillars[(i-1)%3].isEmpty()&&(pillars[(i+1)%3].isEmpty()||pillars[(i+1)%3].Top()>pillars[(i-1)%3].Top())){
min=pillars[(i-1)%3].Pop();
pillars[(i+1)%3].Push(min);
System.out.println(pillars[(i-1)%3]+"->"+pillars[(i+1)%3]);
}else{
min=pillars[(i+1)%3].Pop();
pillars[(i-1)%3].Push(min);
System.out.println(pillars[(i+1)%3]+"->"+pillars[(i-1)%3]);
}
k++;
}
}
}
//主函數,用來測試的。3表示3個盤子。
public static void main(String args[]){
new Hannuota(3).function();
}
}
class Pillar{//構造一個新類,表示柱子,實際是當一個棧在用
private int[] s;
private int top;
private String name;
public String toString(){
return name;
}
//這個構造函數用來構造BC兩個柱子,下面那個用來構造柱子A。其實也可以寫成一個構造函數。
public Pillar(int max,String name){
s = new int[max];
top = -1;
this.name = name;
for(int i=0;i<max;i++){
s[i] = max+1;
}
}
public Pillar(int n,int max,String name){
s = new int[max];
top = n-1;
this.name = name;
for(int i=0;i<max;i++){
s[i] = max - i;
}
}
//這後面這些就是棧的基本方法了,不用介紹了吧
public boolean isEmpty(){
return top==-1?true:false;
}
public int Top (){
return s[top];
}
public int Pop(){
return s[top--];
}
public void Push(int x){
s[++top] = x;
}
}
演算法是這個
首先容易證明,當盤子的個數為n時,移動的次數應等於2^n - 1。
首先把三根柱子按順序排成品字型,把所有的圓盤按從大到小的順序放在柱子A上。
根據圓盤的數量確定柱子的排放順序:若n為偶數,按順時針方向依次擺放 A B C;
若n為奇數,按順時針方向依次擺放 A C B。
(1)按順時針方向把圓盤1從現在的柱子移動到下一根柱子,即當n為偶數時,若圓盤1在柱子A,則把它移動到B;
若圓盤1在柱子B,則把它移動到C;若圓盤1在柱子C,則把它移動到A。
(2)接著,把另外兩根柱子上可以移動的圓盤移動到新的柱子上。
即把非空柱子上的圓盤移動到空柱子上,當兩根柱子都非空時,移動較小的圓盤
這一步沒有明確規定移動哪個圓盤,你可能以為會有多種可能性,其實不然,可實施的行動是唯一的。
(3)反復進行(1)(2)操作,最後就能按規定完成漢諾塔的移動。
這玩意要非遞歸真麻煩。需不需要加點注釋?
其實我不明白幹嘛非要非遞歸。。。
F. 漢諾塔遞歸演算法是什麼
漢諾塔遞歸演算法是:f(n)=2^n-1。
漢諾塔,又稱河內塔,是一個源於印度古老傳說的益智玩具。大梵天創造世界的時候做了三根金剛石柱子,在一根柱子上從下往上按照大小順序摞著64片黃金圓盤。
大梵天命令婆羅門把圓盤從下面開始按大小順序重新擺放在另一根柱子上。並且規定,在小圓盤上不能放大圓盤,在三根柱子之間一次只能移動一個圓盤。
法國數學家愛德華·盧卡斯曾編寫過一個印度的古老傳說:在世界中心貝拿勒斯(在印度北部)的聖廟里,一塊黃銅板上插著三根寶石針。印度教的主神梵天在創造世界的時候,在其中一根針上從下到上地穿好了由大到小的64片金片,這就是所謂的漢諾塔。
不論白天黑夜,總有一個僧侶在按照下面的法則移動這些金片:一次只移動一片,不管在哪根針上,小片必須在大片上面。僧侶們預言,當所有的金片都從梵天穿好的那根針上移到另外一根針上時,世界就將在一聲霹靂中消滅,而梵塔、廟宇和眾生也都將同歸於盡。
不管這個傳說的可信度有多大,如果考慮一下把64片金片,由一根針上移到另一根針上,並且始終保持上小下大的順序。
這需要多少次移動呢?這里需要遞歸的方法。假設有n片,移動次數是f(n)顯然f(1)等於1,f(2)等於3,f(3)=7,且f(k+1)=2*f(k)+1。此後不難證明f(n)=2^n-1。n=64時。
假如每秒鍾一次,共需多長時間呢:一個平年365天有31536000 秒,閏年366天有31622400秒,平均每年31556952秒,計算一下:18446744073709551615秒。
這表明移完這些金片需要5845.54億年以上,而地球存在至今不過45億年,太陽系的預期壽命據說也就是數百億年。真的過了5845.54億年,不說太陽系和銀河系,至少地球上的一切生命,連同梵塔、廟宇等,都早已經灰飛煙滅。
G. 漢諾塔遞歸演算法是什麼
如下:
1、漢諾塔(又稱河內塔)問題是源於印度一個古老傳說的益智玩具。大梵天創造世界的時候做了三根金剛石柱子,在一根柱子上從下往上按照大小順序摞著64片黃金圓盤。
大梵天命令婆羅門把圓盤從下面開始按大小順序重新擺放在另一根柱子上。並且規定,在小圓盤上不能放大圓盤,在三根柱子之間一次只能移動一個圓盤。
2、抽象為數學問題:從左到右有A、B、C三根柱子,其中A柱子上面有從小疊到大的n個圓盤,現要求將A柱子上的圓盤移到C柱子上去,期間只有一個原則:一次只能移到一個盤子且大盤子不能在小盤子上面,求移動的步驟和移動的次數。
演算法分析(遞歸演算法):
實現這個演算法可以簡單分為三個步驟:把n-1個盤子由A 移到 B;把第n個盤子由 A移到 C;把n-1個盤子由B 移到 C。從這里入手,在加上上面數學問題解法的分析,我們不難發現,移到的步數必定為奇數步。
1、中間的一步是把最大的一個盤子由A移到C上去。
2、中間一步之上可以看成把A上n-1個盤子通過藉助輔助塔(C塔)移到了B上。
3、中間一步之下可以看成把B上n-1個盤子通過藉助輔助塔(A塔)移到了C上。
H. 漢諾塔遞歸演算法是什麼
漢諾塔問題實際上就是要將柱子A上由小到大排列的圓環按照相同的大小順序移動到柱子C,之間的過程可以使用柱子B。
其遞歸的歸納思想是這樣的:
(1)首先,當只有一個盤子的時候只需要將A上的1號盤子移動到C上就行了
(2)當有2個盤子在A上的時候,需要將A上的1號盤子(由上往下數)移動到B上,再將A上的2號盤子移動到C上,之後將B上的1號盤子移動到C上
(3)當有3個盤子在A上的時候,需要將A上的1號和2號盤子移動到B上(需要藉助C),之後將A上的3號盤子移動到C上,再將B上的盤子移動到C上(需要藉助A)
(...)以此類推
(N)當有N個盤子在A上的時候,需要將A上的N-1個盤子移動到B上(需要藉助C),之後將A上的第N個盤子移動到C上,再將B上的盤子移動到C上(需要藉助A)
起源
漢諾塔(又稱河內塔)問題是源於印度一個古老傳說的益智玩具。大梵天創造世界的時候做了三根金剛石柱子,在一根柱子上從下往上按照大小順序摞著64片黃金圓盤。
大梵天命令婆羅門把圓盤從下面開始按大小順序重新擺放在另一根柱子上。並且規定,在小圓盤上不能放大圓盤,在三根柱子之間一次只能移動一個圓盤。
I. java遞歸解決漢諾塔時報錯:類型 PrintStream 中的方法 println(boolean)對於參數(void)不適用。
System.out.println(f8(3, "A", "B", "C"));改為f8(3, "A", "B", "C");
J. 漢諾塔遞歸演算法是什麼
漢諾塔遞歸演算法是演算法分析。實現這個演算法可以簡單分為三個步驟:把n-1個盤子由A 移到 B;把第n個盤子由 A移到 C,把n-1個盤子由B 移到 C。
漢諾塔的來源及應用
相傳在古印度聖廟中,有一種被稱為漢諾塔(Hanoi)的游戲。該游戲是在一塊銅板裝置上,有三根桿(編號A、B、C),在A桿自下而上、由大到小按順序放置64個金盤。
游戲的目標:把A桿上的金盤全部移到C桿上,並仍保持原有順序疊好。操作規則:每次只能移動一個盤子,並且在移動過程中三根桿上都始終保持大盤在下,小盤在上,操作過程中盤子可以置於A、B、C任一桿上。
漢諾塔問題是用遞歸方法求解的一個典型問題,在實際教學中,可以在傳統教學方式的基礎上,利用計算機輔助教學進行演算法的模擬演示教學,使學生更容易接受和理解遞歸演算法的思想,不但能提高學生的學習興趣,而且還能取得較好的教學效果。