C语言中的递归函数,我觉得好难懂,这正常吗你们觉得难吗
谢邀。
我也这么觉得哈哈,我当初学习C语言时,觉得最难的就是“递归”了,比指针还难理解(C语言中的指针,很多人都认为难以理解)。
那什么是“递归”呢?我有一天翻词典时,看到词典这么解释一个词:
惊人的:用来形容惊人的形容词。
这要么是恶搞,要么就是玩笑。然而在数学上确实有很多概念是用自己定义的,举个例子:n的阶乘等于n乘以n-1的阶乘,并且0的阶乘等于1。咋一看,似乎它并没有说清楚什么是阶乘,但是这样的描述,却足以让人知道怎样计算阶乘。例如计算4的阶乘:
4!=4x3!=4x3x2!=4x3x2x1!=4x3x2x1x0!=4x3x2x1x1=24并不用细究阶乘到底是什么,只需要按照定义去计算即可,当然,这种定义方式必须要有一个“基础条件”,比如阶乘的“基础条件”就是0!=1。如果没有“基础条件”,阶乘只会无限往下推,没有尽头。
C语言中,什么是递归函数?说了半天阶乘,就是为“递归”做铺垫的,如果一个概念需要用到自身,我们就称它的定义是递归的。那显然,递归函数一定是调用了自身的函数,这么说有点虚,来看看实例吧,下面用C语言计算n的阶乘。我们已经知道,递归最重要的就是“基础条件”了,我们先把阶乘的基础条件写好:
上面的代码实现了0的阶乘等于1,那如果n大于0呢?按照阶乘的定义,应该是nxfatorial(n-1),用代码实现就是:
这就用C语言实现了计算n的阶乘。factorial函数调用了自己,所以factorial是递归函数。事实上,不仅仅是直接调用自己,间接调用自己也属于递归函数。比如,A调用了函数B,函数B又调用了A,那A也是递归函数。
那,递归函数是怎么执行的呢?为了方便解释,我们在factorial函数的else部分加几个局部变量:
这里以factorial(3)为例,用实线箭头表示调用,用虚线箭头表示返回,右边的框表示在调用和返回过程中各函数调用的局部变量的变化情况。
我们看图右边表示存储空间的框的变化过程,随着函数调用的层层深入,存储空间的一端逐渐增长,然后随着函数的层层退出,存储空间的这一端又逐渐缩短,这是一种具有特定性质的数据结构。
它的特性就是只能在某一端增长或缩短,并且每次访问参数和局部变量时只能访问这一末端的单元,而不能访问内部的单元,比如当factorial(2)的存储空间位于末端时,只能访问它的参数和局部变量,而不能访问factorial(3)和main()的参数和局部变量。
具有这种性质的数据结构称为堆栈或栈(Stack)。每个函数调用的参数和局部变量的存储空间(图里的一个小方框)称为一个栈帧(StackFrame)。系统为每个程序的运行预留了栈空间,函数调用时就在这个栈空间里分配栈帧,函数返回时就释放栈帧。
可以看出,写C语言递归函数最重要的就是一定要定义好“基础条件”,不然函数就会永远调用下去,知道系统资源耗尽程序崩溃为止。递归和循环是等价的,用循环能做的事用递归都能做,反之亦然,事实上有的编程语言(如某些LISP)只有递归而没有循环。
计算机硬件能做的所有事情就是数据存取、运算、测试和分支、循环(或递归),在计算机上运行的高级语言写的程序当然也不可能做到更多的事情,虽然高级语言有丰富的语法特性,但也只是为做这些事情提供一些方便。那么,为什么计算机是这样设计的?为什么想到计算机需要具有这几种功能,而不是更多或者更少?这些要归功于早期的计算机科学家,例如AlanTuring,他们在计算机还没有诞生的年代从数学理论上为计算机的设计指明了方向。欢迎在评论区一起讨论,质疑。文章都是手打原创,每天最浅显的介绍C语言、linux等嵌入式开发,喜欢我的文章就关注一波吧,可以看到最新更新和之前的文章哦。
c++程序运行结束后如何返回开头
要返回程序开头可以使用循环语句,例如while或者for语句,让程序在执行结束后回到开始的地方重新执行。具体实现需要在while或for语句的条件语句中判断是否需要重新执行,从而设计出相应的语句块。需要注意的是要避免死循环的情况发生,避免程序一直在循环中执行无法跳出。
c++循环和递归哪个快
一定是循环快,递归是一层层返回的。
递归相对于循环来说,占用空间大,对于大的数据将出现非正常终止的情况。
所以,在c++循环和递归中,使用循环比使用递归更快。
但也有例外。如使用递归和循环计算斐波那契数列的C++代码,结果证明它们非常相似。
c++怎么一起使用多个函数
c++可以通过在主函数外定义其他函数,并在主函数中调用这些函数的方式,一起使用多个函数。
1.在c++中,定义函数是为了将一些操作封装起来,使代码更加高效和易于维护。
在主函数外定义其他函数,可以让代码更加简洁清晰,并有利于实现函数的复用。
2.在需要一起使用多个函数时,可以通过在主函数中按照顺序调用这些函数来实现。
3.多个函数之间可以通过参数传递和返回值传递信息。
可以传递所需的对象实例、变量和其他数据以利于代码功能的扩展和调用。
1.如果函数较多,可以将其定义在独立的头文件中,再在需要使用的文件中包含该头文件,有利于代码的组织和管理。
2.合理地使用全局变量和静态变量,可以方便地在多个函数中传递信息。
3.函数的调用可以通过递归调用和回调函数等方式实现。
C++怎么利用递归实现单线链表的反向输出
/*单向链表的反向输出*/
#include
#include
#defineMAX_LEN10
typedefstruct_LINKNODE
{
intvalue;
struct_LINKNODE*next;
}LINKNODE;
/*链表逆置的原理就是前插,把原链表中的元素一个一个的前插到新的链表中*/
LINKNODE*revertLink(LINKNODE*head)
{
LINKNODE*revert=NULL;
LINKNODE*temp=NULL;
while(head!=NULL)
{
temp=head->next;
head->next=revert;
revert=head;
head=temp;
}
returnrevert;
}
voidmain()
{
intarray[MAX_LEN]={0,1,2,3,4,5,6,7,8,9};
LINKNODE*head=NULL;
LINKNODE*curNode=NULL;
LINKNODE*temp=NULL;
LINKNODE*revert=NULL;
for(inti=0;i
c语言中10的乘方函数
C语言中,10的乘方函数输入方法如下:
在C语言中并没有直接的乘方计算符号,不过有库函数pow可以达到该目的。
pow函数形式为:
doublepow(doublea,doublen);
要调用该函数需要。
#include
功能为计算a的n次方值并返回。
于是10的n次方可以写作
pow(10,n);