C指针原理(40)-递归(1)
一、遞歸
遞歸在計算機科學(xué)中,是指在函數(shù)的定義中使用函數(shù)自身的方法,遞歸是進(jìn)行循環(huán)的一種技巧(在類lisp等函數(shù)語言中它也是實現(xiàn)循環(huán)的主要甚至唯一途徑,比如下面的LISP代碼)。
1、
費波那西數(shù)列(意大利語:Successione di Fibonacci),又譯費波拿契數(shù)、斐波那契數(shù)列、費氏數(shù)列、黃金分割數(shù)列。
在數(shù)學(xué)上,費波那西數(shù)列是以遞歸的方法來定義:
遞歸是完成費波那西數(shù)列計算的方法之一,費波那西數(shù)列由0和1開始,之后的費波那西系數(shù)就由之前的兩數(shù)相加。
、rainfuck解釋器C語言實現(xiàn)
Brainfuck,是一種極小化的計算機語言,它是由Urban Müller在1993年創(chuàng)建的。一種簡單的、可以用最小的編譯器來實現(xiàn)的、符合圖靈完全思想的編程語言。這種語言由八種運算符構(gòu)成,brainfuck的計算方式如此與眾不同,基于一個簡單的機器模型,除了指令,這個機器還包括:一個以字節(jié)為單位、被初始化為零的數(shù)組、一個指向該數(shù)組的指針(初始時指向數(shù)組的第一個字節(jié))、以及用于輸入輸出的兩個字節(jié)流。
下面是這八種狀態(tài)的描述,其中每個狀態(tài)由一個字符標(biāo)識:
字符
含義
指針加一
<
指針減一
指針指向的字節(jié)的值加一
指針指向的字節(jié)的值減一
.
輸出指針指向的單元內(nèi)容(ASCII碼)
,
輸入內(nèi)容到指針指向的單元(ASCII碼)
[
如果指針指向的單元值為零,向后跳轉(zhuǎn)到對應(yīng)的]指令的次一指令處
]
如果指針指向的單元值不為零,向前跳轉(zhuǎn)到對應(yīng)的[指令的次一指令處
可在這個頁面找到這個語言的相關(guān)內(nèi)容:http://www.muppetlabs.com/~breadbox/bf/,該網(wǎng)址提供了一個不錯的簡單高效的brainfuck解釋器源代碼,代碼中涉及數(shù)組、指針等C指針的應(yīng)用。
首先,完成這個解釋器,該程序?qū)λ枰玫降淖兞孔髁巳缦侣暶?#xff1a;
1、數(shù)組變量
char a[5000], f[5000]
其中a
#include <stdio.h>
int p, r, q;
char a[5000], f[5000], b, o, *s=f;
void interpret(char *c)
{
char *d; int tmp;
r++;
while( *c ) {
//if(strchr("<>+-,.[]\n",*c))printf("%c",*c);switch(o=1,*c++) {case '<': p--; break;case '>': p++; break;case '+': a[p]++; break;case '-': a[p]--; break;case '.': putchar(a[p]); fflush(stdout); break;case ',': tmp=getchar();if (tmp == EOF) a[p]=0; else a[p]=tmp;break;case '[':for( b=1,d=c; b && *c; c++ )
b+=*c==’[’, b-=*c==’]’;
if(!b) {
c[-1]=0;
while( a[p] )
interpret(d);
c[-1]=’]’;
break;
}
case ‘]’:
puts(“UNBALANCED BRACKETS”), exit(0);
default: o=0;
}
if( p<0 || p>100)
puts(“RANGE ERROR”), exit(0);
}
r–;
}
int main(int argc,char *argv[])
{
FILE *z;
q=argc;
if((z=fopen(argv[1],“r”))) {
while( (b=getc(z))>0 )
*s++=b;
*s=0;
interpret(f);
}
return 0;
}
1、下面的 fib函數(shù)是C語言的實現(xiàn),函數(shù)反復(fù)調(diào)用自身實現(xiàn)計算
執(zhí)行上述程序:
#include <stdio.h>
long fib_n(long,long,int);
int main(){
fib_n(0, 1, 40);
return 0;
}
int i=0;
long fib_n(long curr,long next,int n) {
printf(“第%d項:%ld\n”,i++,curr);
if (n == 0) {return curr;} else {return fib_n(next, curr+next, n-1);}}
執(zhí)行程序,main以40為參數(shù)n的值,調(diào)用fib,fib陸續(xù)輸出前41個費波那西系數(shù)的值,也是說數(shù)列中的41個數(shù)(因為第1個數(shù)0不是第一項,而是第零項):
dp@dp:~ % gcc fib.c -o fib
dp@dp:~ % ./fib
第0項:0
第1項:1
第2項:1
第3項:2
第4項:3
第5項:5
第6項:8
第7項:13
第8項:21
第9項:34
第10項:55
第11項:89
第12項:144
第13項:233
第14項:377
第15項:610
第16項:987
第17項:1597
第18項:2584
第19項:4181
第20項:6765
第21項:10946
第22項:17711
第23項:28657
第24項:46368
第25項:75025
第26項:121393
第27項:196418
第28項:317811
第29項:514229
第30項:832040
第31項:1346269
第32項:2178309
第33項:3524578
第34項:5702887
第35項:9227465
第36項:14930352
第37項:24157817
第38項:39088169
第39項:63245986
第40項:102334155
其算法可描述如下:
(1)fib函數(shù)在數(shù)列不為0時,進(jìn)入遞歸狀態(tài),反復(fù)調(diào)用自己(也就是fib)。
這個過程雖然調(diào)用的都是fib函數(shù),但每次調(diào)用的參數(shù)都不一定一致辭,因為每次調(diào)用函數(shù),都將新的參數(shù)傳送給fib函數(shù),每次fib函數(shù)的執(zhí)行需要的參數(shù)都是上次fib函數(shù)在執(zhí)行過程中傳遞的。此外,函數(shù)的參數(shù)傳遞方式是通過函數(shù)所屬的堆棧完成的,這意味著雖然遞歸多次反復(fù)調(diào)用fib函數(shù),但參數(shù)只是在本次fib函數(shù)執(zhí)行中用到,使用完畢后堆棧空間就將本次所用的參數(shù)釋放。fib對fib自身進(jìn)行不斷調(diào)用(代碼中的“fib_n(next, curr+next, n-1)”),每次調(diào)用fib_n函數(shù),curr參數(shù)在增長中(curr參數(shù)表示數(shù)列中的當(dāng)前項,初始值為0,每次新值為next),而next參數(shù)也在增長(next參數(shù)表示數(shù)列中的下一項,初始值為1,每次新值為curr+next),n參數(shù)在減少中(n是一個計數(shù)器,注意這個計數(shù)器到0才算結(jié)束,每次減少1,n初始值為40,n控制了生成的費波那西數(shù)列的數(shù)的數(shù)量)。
(2)在n值等于0時,所有對fib函數(shù)的調(diào)用結(jié)束了,生成的費波那西數(shù)的數(shù)量達(dá)到了程序要求。在數(shù)列的開始處(代碼中的“n==0”),最后一次調(diào)用fib函數(shù)完成,函數(shù)返回了程序要求的數(shù)列中最后一個數(shù)的計算(代碼中的“return curr;”),這時的curr等于102334155)。
總結(jié)
以上是生活随笔為你收集整理的C指针原理(40)-递归(1)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C指针原理(39)-GLIB
- 下一篇: Websocket判断逻辑Bug