當前位置:首頁 » 操作系統 » 遞歸演算法for

遞歸演算法for

發布時間: 2022-08-18 03:09:36

『壹』 c語言遞歸演算法

本人學c++,c的語法已經淡忘了,但是遞歸不管什麼語言都是一個原理
其實簡單一點來說就像數學裡面的數列的通項公式:
例如一個數列是2,4,6,8,10......
很容易就可以得到通項公式是a[n]=2*n n是大於0的整數
你肯定學過這個數列的另外一種表示方式就是: a[1]=2, a[n]=a[n-1]+2 n是大於1的整數
其實這就是一個遞歸的形式,只要你知道初始項的值,未知項和前幾項之間的關系就可以知道整個數列。
程序例子:比如你要得到第x項的值
普通循環:
for(int i=1; i<=n; i++)
if (i == x)
cout << 2*i; /*cout 相當於 c裡面的printf,就是輸出.*/
遞歸:
int a(int x) {
if (x = 1)
return 2; /* 第一項那肯定是2了,這個也是遞歸的終止條件! */
else return a(x-1)+2; /* 函數自身調用自身是遞歸的一個特色 */
比如x=4,那麼用數學表示就是a(4)=a(3)+2=(a(2)+2)+2=((a(1)+2)+2)+2
其實遞歸方法最接近自然,也是最好思考的一個方法,難點就是把對象建模成遞歸形式,但是好多問題本身就是以遞歸形式出現的。
普通遞歸就是數據結構上的堆棧,先進後出。
例如上面x=4,把a(4)放入棧底,然後放入a(3),然後a(2),a(1),a(1)的值已知,出棧,a(1)=2,a(2)出棧a(2)=a(1)+2=2+2=4,a(3)出棧a(3)=a(2)+2=(a(1)+2)+2=6,a(4)出棧a(4)=a(3)+2=(a(2)+2)+2=((a(1)+2)+2)+2=8
再比如樓上的階乘例子,當n=0 或 1時,0!=1,1!=1,這個是階乘的初始值,也是遞歸的終止條件。然後我們知道n!=n*(n-1)!,當n>1時,這樣我們又有了遞歸形式,又可以以遞歸演算法設計程序了。(樓上已給出譚老的程序,我就不寫了)。
我給出一種優化的遞歸演算法---尾遞歸。
從我給出的第一演算法可以看出,先進棧再出棧,遞歸的效率是很低的。速度上完全比不上迭代(循環)。但是尾遞歸引入了一個新的函數參數,用這個新的函數參數來記錄中間值.
普通遞歸階乘fac(x),就1個x而已,尾遞歸用2個參數fac(x,y),y存放階乘值。
所以譚老的程序就變成
// zysable's tail recursive algorithm of factorial.
int fac(int x, int y) {
if (x == 1)
return y;
else return fac(x-1, y*x);}
int ff(int x) {
if (x == 0)
return 1;
else return fac(x,1);}
對於這個程序我們先看函數ff,函數ff其實是對fac的一個封裝函數,純粹是為了輸入方便設計的,通過調用ff(x)來調用fac(x,1),這里常數1就是當x=1的時候階乘值了,我通過走一遍當x=3時的值即為3!來說明一下。
首先ff(3),x!=0,執行fac(3,1).第一次調用fac,x=3,y=1,x!=1,調用fac(x-1,y*x),新的x=2,y=3*1=3,這里可以看到,y已經累計了一次階乘值了,然後x還是!=1,繼續第三次調用fac(x-1,y*x),新的x=1,y=2*3=6,然後x=1了,返回y的值是6,也就是3!.你會發現這個遞歸更類似於迭代了。事實上我們用了y記錄了普通遞歸時候,出棧的乘積,所以減少了出棧後的步驟,而且現在世界上很多程序員都在倡議用尾遞歸取消循環,因為有些在很多解釋器上尾遞歸比迭代稍微效率一點.
基本所有普通遞歸的問題都可以用尾遞歸來解決。
一個問題以遞歸來解決重要的是你能抽象出問題的遞歸公式,只要遞歸公式有了,你就可以放心大膽的在程序中使用,另外一個重點就是遞歸的終止條件;
其實這個終止條件也是包含在遞歸公式裡面的,就是初始值的定義。英文叫define initial value. 用普通遞歸的時候不要刻意讓自己去人工追蹤程序,查看運行過程,有些時候你會發現你越看越不明白,只要遞歸公式轉化成程序語言正確了,結果必然是正確的。學遞歸的初學者總是想用追蹤程序運行來讓自己來了解遞歸,結果越弄越糊塗。
如果想很清楚的了解遞歸,有種計算機語言叫scheme,完全遞歸的語言,因為沒有循環語句和賦值語句。但是國內人知道的很少,大部分知道是的lisp。
好了,就給你說到這里了,希望你能學好遞歸。

PS:遞歸不要濫用,否則程序極其無效率,要用也用尾遞歸。by 一名在美國的中國程序員zysable。

『貳』 遞歸演算法

遞歸演算法
遞歸演算法流程
遞歸過程一般通過函數或子過程來實現。遞歸演算法:在函數或子過程的內部,直接或者間接地調用自己的演算法。
遞歸演算法的特點
遞歸演算法是一種直接或者間接地調用自身的演算法。在計算機編寫程序中,遞歸演算法對解決一大類問題是十分有效的,它往往使演算法的描述簡潔而且易於理解。 遞歸演算法解決問題的特點: (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); }
編輯本段遞歸演算法簡析(PASCAL語言)
遞歸是計算機科學的一個重要概念,遞歸的方法是程序設計中有效的方法,採用遞歸編寫 程序能是程序變得簡潔和清晰.
一 遞歸的概念
1.概念 一個過程(或函數)直接或間接調用自己本身,這種過程(或函數)叫遞歸過程(或函數). 如: procere a; begin . . . a; . . . end; 這種方式是直接調用. 又如: procere c(形參);forward; procere b; 局部說明 begin . . c(實參); . . end; procere c; 局部說明; begin . . b; . . end; 這種方式是間接調用. 例1計算n!可用遞歸公式如下: fac:=n*fac(n-1) {當n>0時} fac(n)={ fac:=1; { 當n=0時} 可編寫程序如下: program facn; var n:integer; function fac(n:integer):real; begin if n=0 then fac:=1 else fac:=n*fac(n-1); end; begin write('n=');readln(n); writeln(n,'!=',fac(n):0:0); end. 例2 樓梯有n階台階,上樓可以一步上1階,也可以一步上2階,編一程序計算共有多少種不同的走法. 設n階台階的走法數為f(n) 顯然有 n=1 f(n)={ f(n-1)+f(n-2) n>2 可編程序如下: program louti; var n:integer; function f(x:integer):integer; begin if x=1 then f:=1 else if x=2 then f:=2 else f:=f(x-1)+f(x-2); end; begin write('n=');read(n); writeln('f(',n,')=',f(n)) end.
二 如何設計遞歸演算法
1.確定遞歸公式 2.確定邊界(終了)條件
三 典型例題
例3 漢諾塔問題 如圖:已知有三根針分別用1,2,3表示,在一號針中從小放n個盤子,現要求把所有的盤子 從1針全部移到3針,移動規則是:使用2針作為過度針,每次只移動一塊盤子,且每根針上 不能出現大盤壓小盤.找出移動次數最小的方案. 程序如下: program hanoi; var n:integer; procere move(n,a,b,c:integer); begin if n=1 then writeln(a,'->',c) else begin move(n-1,a,c,b); writeln(a,'--->',c); move(n-1,b,a,c); end; end; begin write('Enter n='); read(n); move(n,1,2,3); end. 例4 快速排序 快速排序的思想是:先從數據序列中選一個元素,並將序列中所有比該元素小的元素都放到它的右邊或左邊,再對左右兩邊分別用同樣的方法處之直到每一個待處理的序列的長度為1, 處理結束. 程序如下: program kspv; const n=7; type arr=array[1..n] of integer; var a:arr; i:integer; procere quicksort(var b:arr; s,t:integer); var i,j,x,t1:integer; begin i:=s;j:=t;x:=b ; repeat while (b[j]>=x) and (j>i) do j:=j-1; if j>i then begin t1:=b; b:=b[j];b[j]:=t1;end; while (b<=x) and (i<j) do i:=i+1; if i<j then begin t1:=b[j];b[j]:=b;b:=t1; end until i=j; b:=x; i:=i+1;j:=j-1; if s<j then quicksort(b,s,j); if i<t then quicksort(b,i,t); end; begin write('input data:'); for i:=1 to n do read(a); writeln; quicksort(a,1,n); write('output data:'); for i:=1 to n do write(a:6); writeln; end.
編輯本段{遞歸的一般模式}
procere aaa(k:integer); begin if k=1 then (邊界條件及必要操作) else begin aaa(k-1); (重復的操作); end; end;
開放分類:
編程,計算機,演算法

引自:http://ke..com/view/1733593.htm

『叄』 c語言遞歸演算法

用遞歸法計算n!
用遞歸法計算n!可用下述公式表示:
n!=1 (n=0,1)
n×(n-1)! (n>1)
按公式可編程如下:
long ff(int n)
{
long f;
if(n<0) printf("n<0,input error");
else if(n==0||n==1) f=1;
else f=ff(n-1)*n;
return(f);
}
main()
{
int n;
long y;
printf("\ninput a inteager number:\n");
scanf("%d",&n);
y=ff(n);
printf("%d!=%ld",n,y);
}

程序中給出的函數ff是一個遞歸函數。主函數調用ff 後即進入函數ff執行,如果n<0,n==0或n=1時都將結束函數的執行,否則就遞歸調用ff函數自身。由於每次遞歸調用的實參為n-1,即把n-1的值賦予形參n,最後當n-1的值為1時再作遞歸調用,形參n的值也為1,將使遞歸終止。然後可逐層退回。
下面我們再舉例說明該過程。設執行本程序時輸入為5,即求5!。在主函數中的調用語句即為y=ff(5),進入ff函數後,由於n=5,不等於0或1,故應執行f=ff(n-1)*n,即f=ff(5-1)*5。該語句對ff作遞歸調用即ff(4)。
進行四次遞歸調用後,ff函數形參取得的值變為1,故不再繼續遞歸調用而開始逐層返回主調函數。ff(1)的函數返回值為1,ff(2)的返回值為1*2=2,ff(3)的返回值為2*3=6,ff(4)的返回值為6*4=24,最後返回值ff(5)為24*5=120。

『肆』 分別用for循環和遞歸法求N!

VB代碼:
------------------------------------------------------------------------
for循環
_____________________________________________
private function jiechengfor(byval n as integer)
dim i as integer,dim jiecheng as long
jiecheng=1
for i =n to 1 step -1
jiecheng=jiecheng*i
next i
jiechengfor=jiecheng
end function
____________________________________________
遞歸法:
____________________________________________
private function jiechengDG(byval n as integer)
if n<2 then
jiechengdg=1
else
jiechengdg=jiechengdg(n-1)*n
end if
end function
____________________________________________
調用方法:
—————————————————————————
private sub command1_click()
dim n as integer
n=inputbox("請輸入n的值:")
msgbox("使用for循環算出" & n & "的階乘等於:" & jiechengfor(n) & vbcrlf & "使用遞歸算出" & n & "的階乘等於:" & jiechengdg(n) )
end sub

『伍』 計算機編程中的for循環和while循環算不算遞歸演算法請高手幫忙~

不算。
所謂遞歸是指函數、過程、子程序在運行過程序中直接或間接調用自身而產生的重入現象。
而for和while只是重復執行循環體。

『陸』 簡單的遞歸演算法

我不明白什麼是對對象依賴太大。這個全用static,不存在對象:)
public class DrawStar {
public static void main(String[] args) {
drawStar(5);
}

private static void drawStar(int n) {
if (n > 0) {
drawLine(n);
drawStar(n - 1);
drawLine(n);
}
}

private static void drawLine(int n) {
for (int i = 0; i < n; i++)
System.out.print("*");
System.out.println();
}
}

『柒』 關於遞歸演算法的問題

void path(AdjMaxix adj, int i, int j, int k) //定義一個函數,形參是 adj,i,j,k;
{
int s; //定義變數s;
if (p[k]==j) // 設定循環條件;
{
for (s=0; s<=k; s++)
cout << p[s] << "; ";//依次輸出平p[i];
cout << endl; // 輸出p[i]後換行;
}
else //如果不符p[k]==j條件,則;
{
s=0;
while (s<adj.n)
{
if (adj.edges[p[k]][s]==1 && visited [s]==0)
{
visited[s]=1;
p[k+1]=s;
path(adj,i,j,k+1);
visited[s]=0;
}
s++;
}
}
}
void dispath(AdjMaxix adj, int i, int j)
{
int k;
p[0]=i;
for (k=0;k<MaxVex;k++)
visited[i]=0;
path(adj,i,j,0);
}

『捌』 遞歸演算法是怎麼運行的

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

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

『玖』 全排列遞歸演算法中的for里為什麼要交換兩次i,k啊

舉個例子 比如現在數組的數據是 123 你的演算法是侄兒樣的 1和3先交換 變成了321 然後遞歸 2和1交換 變成了312 然後遞歸 滿足if語句條件輸出 然後在逐層反回 還是 123 只不過這次應該是23交換了 這樣在遞歸 才有能把所有的組合找出來 如果你第二次不交換i j 那就是321進入下個循環了 所以會漏掉很多組合

『拾』 求遞歸循環 演算法

#include<stdio.h>#include <windows.h>
void Calc(BYTE *bpData, long nDataSize, int * npMask, long nMaskSize,
long nCurrentLevel, BYTE * bpOutput)
{
if (nCurrentLevel>=nDataSize)
{
long i;
for (i=0; i<nDataSize-1; i++)
{
printf("%d, ", bpOutput[i]);
}
printf("%d\n", bpOutput[i]);
return;
}

//Find if this level is in the Mask arr.
bool bFound = false;
for (long k=0; k<nMaskSize; k++)
{
if (npMask[k] == nCurrentLevel+1)
{
bFound = true;
break;
}
}

if (! bFound)
{
bpOutput[nCurrentLevel] = bpData[nCurrentLevel];
Calc(bpData, nDataSize, npMask, nMaskSize, nCurrentLevel+1, bpOutput);
}else
{
for (long n=0; n<=9; n++)
{
bpOutput[nCurrentLevel] = (BYTE)n;
Calc(bpData, nDataSize, npMask, nMaskSize, nCurrentLevel+1, bpOutput);
}
}
}

void main()
{
BYTE bpTemp[100];
BYTE bp1[1] = {11};
int arr1[1] = {1};
printf("------------------------------------\n");
Calc(bp1, 1, arr1, 0, 0, bpTemp);
getchar();
printf("------------------------------------\n");
Calc(bp1, 1, arr1, 1, 0, bpTemp);
getchar();

BYTE bp2[4] = {11, 12, 13, 14};
int arr2[2] = {1, 2};
printf("------------------------------------\n");
Calc(bp2, 4, arr2, 2, 0, bpTemp);
getchar();

BYTE bp3[8] = {11, 12, 13, 14, 15, 16, 17, 18};
int arr3[4] = {3,4,7,8};
Calc(bp3, 8, arr3, 4, 0, bpTemp);

getchar();
}

使用遞歸函數。
測試了幾種情形。
按回車可以繼續。

熱點內容
網路設置里沒有伺服器是什麼 發布:2025-01-18 09:52:19 瀏覽:343
阿里雲esc伺服器系統 發布:2025-01-18 09:49:16 瀏覽:790
你們家的無線網密碼是多少 發布:2025-01-18 09:47:50 瀏覽:730
renderscriptandroid 發布:2025-01-18 09:32:18 瀏覽:993
安卓手機如何拍游戲素材 發布:2025-01-18 09:30:59 瀏覽:348
廣州日立壓縮機有限公司 發布:2025-01-18 09:15:08 瀏覽:624
伺服器兩條寬頻如何疊加網速 發布:2025-01-18 08:52:17 瀏覽:731
oracle存儲過程集合 發布:2025-01-18 08:42:39 瀏覽:885
洋蔥數學緩存 發布:2025-01-18 08:38:36 瀏覽:919
電影的文件夾都是 發布:2025-01-18 08:21:49 瀏覽:835