递归函数一定要弄清楚这个函数是做什么用的,基于什么条件返回什么结果!

理解C语言递归函数的逐级返回(return) 一个关于递归和return语句的小例子 阅读详情

总结一下:写递归时一定要清楚这个递归函数的每个参数是干嘛用的,以及这个递归函数是干什么用的,返回了什么结果。两篇文章都有提到!

So, here are the steps to writing a recursive function.

  1. Write a prototype for the recursive function.
  2. Write a comment that describes what the function does.
  3. Determine the base case (there may be more than one), and its solution(s).
  4. Determine what smaller problem (or problems) to solve. If it makes it easier for you to follow, save the solutions to the smaller problems to local variables (e.g., small in the sum() example).

    ASSUME the recursive call works (similar to inductive hypothesis in CMSC 250), i.e., that it will correctly compute the answer.

  5. Use the solutions of the smaller problem to solve the larger problem. (If this is done INCORRECTLY, the solutions of the smaller problems will also be computed incorrectly, thus, the assumption in the previous step will fail).
Mission Statements
A very important thing to consider when writing a recursive algorithm is to have a clear idea of our function's "mission statement." For example, in this case I've assumed that a person shouldn't be counted as reporting to him or herself. This means "countEmployeesUnder('Betty')" will return zero. Our function's mission statment might thus be "Return the count of people who report, directly or indirectly, to the person named in  employeeName  - not including the person named  employeeName ."



C M S C     2 1 4 
C o m p u t e r   S c i e n c e   I I 
F a l l   2 0 0 2 



Recursive Functions

What's a Recursive Function?

Technically, a  recursive function is a function that makes a call to itself. To prevent infinite recursion, you need an if-else statement (of some sort) where one branch makes a recursive call, and the other branch does not. The branch without a recursive call is usually the  base case (base cases do not make recursive calls to the function).

Functions can also be mutually recursive. For example, function f() can call function g() and function g() can call function f(). This is still considered recursion because a function can eventually call itself. In this case, f() indirectly calls itself.

Functions can be tail-recursive. In a tail-recursive function, none of the recursive call do additional work after the recursive call is complete (additional work includes printing, etc), except to return the value of the recursive call.

The following is typical of a tail-recursive function return.

   return rec_func( x, y ) ; // no work after recursive call, just return the value of call
The following is NOT tail-recursive.
   return rec_func( x, y ) + 3 ; // work after recursive call, add 3 to result
because once  rec_func is done, it must add 3, and then return that value. Hence, additional work. Hence, not tail-recursive.

It's common, in tail-recursive functions, to have one of the parameters be pass-by-reference (though this is not necessary), which is used to accumulate the answer. Once the base case is reached, you simply return the parameter value, which has the answer. Thus, tail-recursive functions often require an additional parameter, where non tail-recursive functions do not.

The main drawback with recursion is that it can use O(n) space (stack space) when a simple loop may only use O(1). For example, printing an array should only require O(1) space in addition to the array. You just need a looping variable, which requires O(1) space. The recursive solution uses O(n) space.

However, a good compiler can determine if a function is tail-recursive, and internally produce code that runs in O(1) space, thus giving you the benefits of recursion (i.e., recursion is "neat" and compact to write) but with the space efficiency of a loop. Languages other than C++ (say, ML) often require tail-recursion be converted to loops by the compiler. Typical C++ compilers generally (I believe) do not make this optimization.

When to Use Recursion?

Some people think recursion is so neat, they would like to use it all the time. In general, recursion should be used when you know the number of recursive calls isn't excessive. That number depends somewhat on how much memory you have. Usually, a 1000 recursive calls should be fine. Stack sizes can now be several megabytes of memory, which allows recursion to go fairly deep without causing a core dump.

Sometimes recursion is used because it produces a cleaner answer compared to the iterative version. For example, nearly all code written for tree-like structures is recursive. Many sorting algorithms are more naturally written recursively as well.

However, recursive solutions can be VERY inefficient, if you aren't careful. For example, the obvious recursive solution to compute the Nth Fibonacci numbers has exponential running time, even though the loop version runs in O(n). This is one good reason to study algorithms (in CMSC 351)---so you know what the running time of a recursive algorithm is, and decide if that solution is worthwhile.

If it sounds like recursion is always bad, realize that recursion often produces solutions that are very compact (requires few lines of typed code). Code with fewer lines are easier to debug than code with many lines. Writing recursive functions can give you greater confidence that you are coding correctly. Often, writing code that ought to be recursive without recursion (i.e., as loops) produces messy code. You may even have to simulate a stack (recursion uses the program stack behind the scenes) to get the behavior you want.

How to Think Recursively

When you want to write a recursive function, begin by writing its prototype. Define what the recursive function does in English (or whatever language you prefer).

For example, consider the following stand-alone (non-member) function:

 
   // Sums first n elements of arr
   int sum( int arr[], int n ) ;
When you make the call:
 
   sum( arr, 10 ) ;
You know this is summing the first 10 elements of  arr.

Writing down the purpose of the function may seem like a trivial step, but it's important. Students often fail to write recursive functions correctly because they forget what the function is trying to do.

Then, repeat the following to yourself several times: Recursion solves a big problem (of size n, say) by solving one or more smaller problems, and using the solutions of the smaller problems, to solve the bigger problem. For example, suppose you are running for some fund-raising marathon. You have collected a large stack of pledges, but want to know what the total amount that people have pledged to you. This stack is rather large, and you'd rather not do the work yourself.

However, you have many willing friends. You divide the stack of pledges and ask your friend "Could you please add up the dollar amount in pledges in this stack? I've only given you half, so there's half the work to do.". As a sneaky person, you give the other half to another friend, and say the same thing. Once both are done, they will give their answer to you, and you add their results.

Thus, you have broken down the problem into two smaller parts, and asked your friends to do the work.

Now those friends are clever, so they divide the stack into two parts (now each has two stacks with size 1/4) and ask two of their friends. When their friends are done, they return their answer, and the result is summed.

Eventually, there is only a stack of two pledges, and these are given to two friends, and those friends, seeing how silly the problem is now, just tell the first friend the only value on the pledge. There's no need to ask any more friends, because you're down to one pledge (this is the base case).

Thus, recursion is all about breaking a problem down, and solving that, and that smaller problem is solved by breaking it down some more, and trying to solve that. Eventually, you reach an easy solution (the base case), and return the solution.

It's interesting to think about what happens to the stack when this happens. As you make each recursive call, the stack grows larger and larger. When you reach the base case, the recursion is done, and the stack becomes smaller and smaller, as it passes the solution back.

Once you have the prototype written, think about solving the next smaller sized problem. Thus, if the call is:

   sum( arr, n ) ;
what's the next smallest size? What about  n - 1?
   sum( arr, n - 1 ) ;
Suppose someone gave you the answer to this sum. What would you have? This is where it's important to remember how you defined the function. This would give you the sum of the first  n - 1 elements.

Now that you have this solution (which you can assume), what's needed to solve the entire problem? Well, you haven't added arr[ n - 1 ]. So, do that.

Finally, you should deal with the base case, which is the smallest problem (in terms of input size, n) you can solve without any recursive calls. It turns out that

   sum( arr, 0 ) ;
is the smallest input size. While having an array of size 0 may not make sense, it's fine. Just let this value be 0 (since 0, summed to any value, just gives you that value). 0 is the additive identity.

Here's the code:

int sum( int arr[], int n )
{
  if ( n == 0 )  // base case
    return 0 ;   // no recursive call
  else
    {
      int small = sum( arr, n - 1 ) ; // solve smaller problem
      // use solution of smaller to solve larger
      return small + arr[ n - 1 ] ;
    }
}
So, here are the steps to writing a recursive function.
  1. Write a prototype for the recursive function.
  2. Write a comment that describes what the function does.
  3. Determine the base case (there may be more than one), and its solution(s).
  4. Determine what smaller problem (or problems) to solve. If it makes it easier for you to follow, save the solutions to the smaller problems to local variables (e.g., small in the sum() example).

    ASSUME the recursive call works (similar to inductive hypothesis in CMSC 250), i.e., that it will correctly compute the answer.

  5. Use the solutions of the smaller problem to solve the larger problem. (If this is done INCORRECTLY, the solutions of the smaller problems will also be computed incorrectly, thus, the assumption in the previous step will fail).

What Makes Recursion Work

Recursion works only when a problem has a recursive structure. This means that the problem's solution is similar for a large input size as well as a small input size. If reducing the input size causes the solution to look different, then it will be hard to use recursion. However, for the same reason, it can be hard to use loops too. Loops also depend on doing the same thing over and over, but on, say, a different index of an array, or a different node in a linked list.

Also, you must be able to use the solutions of the small problem to help solve the larger one. Again, if the solutions aren't useful to you, then recursion isn't going to be useful.

Fortunately, many problems exhibit this kind of behavior. If you can write it in a loop, there are ways to convert it to recursion (and vice versa).

Misconceptions about Recursion

Suppose function  f() calls  g() and then function  g() calls  h() which then calls  i(). What happens when  i() is done?

As you know, the flow of execution goes back to h() and when that's done, it goes back to g(), when when g() is done, it goes back to f().

This is how the call stack works. Each function call causes some memory to be pushed on a stack. Once the call is done, that memory is popped off the stack, and the flow of control goes back to the function that made the call.

Still, even though most students in 214 have no trouble understanding this idea of a function call and its return, they think that recursion is somehow different. In particular, they think that once the base case is reached, the function is magically done. They think no return occurs, and the previous recursive calls disappear. It doesn't. In this respect, recursive calls are just like regular function calls. In fact, they are not implemented any different (except possibly that they can be optimized) from regular function calls.

For example, if function f() calls f(), which calls f(). Then, when the last call to f() is completed (presumably the base case), you return back to the second call to f(), and when that is done, it goes back to the original call. This is just like non-recursive function calls.

I call this process winding and unwinding. Each recursive call is like walking up one step. Eventually you reach the top step (the base case). When you're done, you back down one step at a time, until you are back at the bottom step (the original call).

Don't forget that even recursive functions return back, just like non-recursive functions do.

The second misconception about recursion is that the base case is only called when the value passed in as argument is the base case value. Technically, this is not wrong. This is when the base case is run.

However, any recursive call (that doesn't end in infinite recursion), eventually calls the base case. Thus, when you call 
sum( arr, 10 ) the base case is eventually called. Some people think the base case only gets called when you call 
sum( arr, 0 ), and while this is true, sum( arr, 0 ) is eventually called when you call sum( arr, 10 ).

The lesson? Base case contributes to the solution of any recursive call (if it doesn't, you have infinite recursion, or a core dump).

Helper Functions

Recursive functions rely heavily on parameters and return values of functions to do their work. Indeed, the basic unit of a recursive function is a function. This may seem obvious, but it really isn't. If you only use loops, then theoretically, you can write one large  main() and never have to write another function again. Loops don't really require functions. Recursion does.

When writing recursive functions, you have to write functions (I suppose one could make main() recursive, and let it do all the work, but it's not very elegant). This has one good side-effect. Functions tend to be shorter if written recursively than if written using loops.

However, because recursive functions rely on parameters and return values, what happens if the function you write doesn't have the parameters you need.

For example, consider a singly linked list. You wish to print out all the values in the list. The prototype in the class header file looks like:

   void print() ;
Without any parameters, you can't write this recursively. What do you do? You write a recursive helper function.
   void printRec( Node * curr ) ; // helper
print() calls  printRec( first ), where  printRec() is the true recursive function.

Often, you need such helpers so you can make recursive calls. The helpers have the parameters you need to make it work. So, print(), while not recursive, makes a call to a helper function which is recursive, and does all the work. print() is basically a "bootstrap" function, which calls the recursive helper function with the correct initial value as argument.

Common Mistakes With Helpers

Just because it's useful to write recursive functions with helpers, don't overdo it. The most common mistake when writing helper functions is to use the EXACT SAME PROTOTYPE.

Thus, you have rec_func which takes two parameter types, which calls rec_func_help which takes the same two parameter types! Every semester, someone does this on an exam (writes a recursive function, which calls a helper with the exact same parameter list), leaving graders to scratch their heads wondering why students are doing this.

Why bother writing a helper when the original function would have been fine? Write helpers only because you need a different parameter list. Otherwise, don't use helper functions.

Avoiding Static/Global Variables

Generally, I put static variables in the same category as global variables, and prefer to avoid them when I can. In particular, using static variables to do recursion can lead to problems. For example, static variables are initialized when the function is initially called for the first time. However, it's hard to re-initialize them afterwards.

Consider

  int sum ( int arr[], int n )
  {
     int result = 0 ;
     if ( n == 0 )
        return result ;
     else {
        result += arr[ n - 1 ] ;
        sum( arr, n - 1 ) ;
     }
  }
This should work fine the first time you call it. However, the second time,  result is not 0, and your answer will be wrong.

Instead, you should always update arguments to the recursive function.

You can "cheat" somewhat by using a reference parameter. This isn't a static variable, nor is it global, though it behaves like a global variable. The "pure" form of recursion avoids those kinds of references (arrays are usually fine because arrays are often not modified in the recursive call).

Nevertheless, you should know how to use reference parameters. Almost always, you need helper recursive functions to use reference parameters. The initial function is not recursive, but declares some local variables and initializes it, then calls the recursive function and passes the variables to the reference parameters.

Converting a Loop to Recursion

Converting a loop to recursion is not as hard as it seems. This is  not how you would normally write a recursive function. To write a recursive function, you generally want to think "recursively".

As mentioned earlier, thinking recursively means solving a large instance of a problem by solving a smaller instance of the problem, assuming that the smaller instance can be solved, and using that solution to solve the bigger problem.

Nevertheless, it's fairly easy to convert a for-loop to recursion, should you choose to do so.

Here's a typical loop.

   for ( <init> ; <cond> ; <update> )
      <body>
This can be converted to two functions: the main function and the helper recursive function.
void recFunc() {
   int loopVar = <init>
   
   recHelperFunc( loopVar );
}

void recHelperFunc( int loopVar ) {
   if ( <cond> ) {
      <body>
      <update>
      recHelperFunc( loopVar ); // recursive call
   }
}
The loop has been replaced by an if-statement. The recursive call at the end replaces the loop. Since the looping variable is being updated, you can save some memory by passing the variable by reference.

However, the looping variable can be passed by value as well. Sometimes, it's nicer to pass by value, because if you pass by reference, then you must pass something that looks like a variable. Passing an expression (e.g., i + 1) is not allowed for a non-const reference, but is permitted for a value parameter.

Let's look at how to convert a simple loop.

   for ( int i = 0 ; i < n ; i++ )
     cout << i << endl;
Suppose that  n is a variable, then, you need two parameters in the recursive helper function.
void recFunc() {
   int i = 0 ;
   recHelperFunc( i, n ) ; // recursive call
}

void recHelperFunc( int i, int n ) {
   if ( i < n ) {  // condition of loop
      cout << i << endl ;
      i++;
      recHelperFunc( i, n ) ; // recursive call
   }
}
In general, you should avoid using ++ on variables that are passed as arguments. In particular, don't use post-increment or post-decrement, since, in principle, the update won't occur until AFTER the function call, and at that point, you will cause infinite recursion.

It's better to update the value prior to calling the function, and pass the variable in. Alternately, if you are passing by value, use an expression that is not side-effecting. i++ has a side effect (it updates i), where as i + 1 is not side effecting (it doesn't update i).

Recall that when you pass an argument by value, a copy is created. Thus, every single time recHelperFunc(), a new copy of i and n are created.

Admittedly, this is somewhat of a waste because n never changes, but recursion often does this.

"Real" Recursion

We can try to write this function more "recursively". That is, to think about how to solve the smaller problem. Initially, you'd think about what kind of function you want. The goal is to print the numbers from 0 to  n - 1. So you can imagine having a function to do this:
void printIt( int n );
The recursive call passes in  n.

Now, what would be a smaller recurisve call?

void printIt( n - 1 );
This function would print out 0 up to  n - 2. If this occurred, what would we do to print the rest? You would print  n - 1. The base case is when  n == 0.

So, here's how you would write the code in a more traditional recursive way.

void printIt( int n ) {
   if ( n == 0 ) { // base case
      cout << 0 << endl;
   }
   else { // recursive case
      printIt( n - 1 );  // recursive call
      cout << n - 1 << endl;
   }
}
Notice that you pass one fewer parameter this way, although it doesn't match up with the loop nearly as well. In general, you would "prefer" to do it this way, because it's more "natural" when writing recursive functions.

Here's an analogy. There are two ways to learn a foreign language. Either learn a foreign language by learning it like native speakers speak it, or learn to translate every word in your native language to the foreign language. The second method works, somewhat, but isn't as "fluent" as the first.

For coding, of course, it doesn't matter which method, as long as it works, but nevertheless, the second method we looked at it more "fluent" since the problem is solved from the usual methodology of solving smaller problems and using it to solve bigger problems.

Occasionally, you must use the loop method to come up with a recursive call, because not all problems are nearly as easy to break down into smaller cases.



http://www.cs.umd.edu/class/fall2002/cmsc214/Tutorial/recursion2.html

http://community.topcoder.com/tc?module=Static&d1=tutorials&d2=recursionPt1

http://community.topcoder.com/tc?module=Static&d1=tutorials&d2=recursionPt2




EEGLAB合辑 | 第一节 往EEGLAB导入数据 1、学习Matlab EEGLAB图形界面建立在强大的Matlab脚本语言之上。要使用EEGLAB构建宏命令和执行自定义和自动化处理的全部功能,就需要能够在Matlab中操纵EEGLAB数据结构。由于时间限制,这个wiki没有提供关于Matlab脚本语言的介绍。相反,用户需要在开始研究之前熟悉Matlab。 2、安装EEGLAB和教程文件 首先下载包含教程数据集的EEGLAB(30MB),附下载地址。 (https://sccn.ucsd.edu/eeglab/downloadtoolbox.php) 解压 阅读详情

相关推荐

深入解析TPS53676 AVSBus接口:协议、帧结构与动态电压调节实战

在数字电源管理领域,动态电压调节(DVS)是实现高性能处理器(如CPU、GPU)节能与性能优化的关键技术。其核心原理在于根据处理器负载实时、精准地调整供电电压,从而在满足性能需求的同时最小化功耗。为实现微秒甚至纳秒级的快速响应,传统的PMBus协议因其协议开销可能成为瓶颈,因此催生了更专注、更低延迟的专用通信接口。AVSBus(自适应电压调节总线)正是PMBus规范中专为点对点、高速电压控制而定义的子集,它继承了PMBus的物理层,但简化了通信流程,其技术价值在于为处理器与电源控制器之间建立了一条高速“专用

weixin_29188043的博客 445

递归函数一定要弄清楚这个函数是做什么用的,基于什么条件返回什么结果!...

总结一下:写递归时一定要清楚这个递归函数的每个参数是干嘛用的,以及这个递归函数是干什么用的,返回了什么结果。两篇文章都有提到! So, here are the steps to writing a recursive function. Write a prototype for the recursive function. Write a comment that describes ...

系统 运维 939

Origin绘制带差异显著性标记的分组均值条形图|科研论文图表教程(附数据格式模板)

传统柱状图虽能呈现组间均值差异,却隐藏个体数据分布;散点图虽能展示原始数据,却难以直观凸显统计显著性。带差异显著性(*)的分组均值条形图——它以“双层叙事”的创新设计,同时呈现群体特征与个体差异。

weixin_50236590的博客 1493

递归

递归函数:指调用自己的函数。 一.递归的特点 1.函数一般使用if-else或分支语句来实现。 2.存在一个或多个条件用来停止递归。 3。每次递归调用会使问题逼近终止条件或情况,直到转化为该条件或情况为止。 (递归递归先递后归,递:层层递进只到最终条件为止,归:带着得到的结果一层层返回到原问题。题外话:翻译还是有点东西的) 递归的分类: 递归分为两种,直接递归和间接递归。 1.直接递归即函数自身调...

n 512

2023年5月青少年软件编程Python等级考试四级真题(含答案和解析)

电子学会,2023年5月,青少年软件编程,Python等级考试,四级真题(含答案和解析)

m0_37554648的博客 904

【车载以太网】Eth Stack Bringup

摘要:本文基于AUTOSAR架构,详细介绍了在TC3xx硬件平台上实现EthStack Bringup的全过程。作者通过配置MCAL和Davinci工具,完成了EthTrcv、Eth、EthIf、EthSM和TcpIp等模块的集成,并解决了16字节内存对齐和以太网速率不匹配等问题。最终实现了PC端与开发板的Ping通,并通过WireShark验证了数据包收发。文章总结了调试中的关键问题与解决方案,强调了实践的重要性,为后续EthStack的深入分析奠定了基础。

qq_36056498的博客 180

QuickSort (recursive)

template void QuickSort(T* a, const int left, const int right) { int i, j, pivot; if(left < right) { i = left + 1; j = right; pivot = a[left]; while(i < j) { while(a[i] < pivot)i++;

georgechen 841

BoT-SORT实战:手把手教你实现BoT-SORT训练和测试

文章目录摘要1、数据准备2、配置BoT-SORT环境2.1、获取代码2.2、创建虚拟环境2.3、安装必要的包2.3.1、安装pytorch2.3.2、安装cython2.3.3、安装Cython-bbox2.3.4、安装faiss2.3.5、安装其他的包3、训练3.1、生成REID数据集3.2、预训练模型3.2.1、ByteTrack预训练模型3.2.2、REID预训练模型3.3、开始训练4、如何更改FASTREID的BackBone?5、测试5.1、测试视频5.2、测试摄像头5.3、多类别测试 摘要 Bo

m0_47867638的博客 2298

C++作业01

Program #2 - Maze TraversalMaze Traversal:You will be given two files that contain ASCII mazes, and your program should first read in the maze into arrays (or vectors) and then recursively fin

skyinter的专栏 1361

【Microchip】微芯 MPLAB® X IDE开发环境新建项目(点亮1颗LED灯)(常用右键菜单快捷键)

1.新建项目2. 选择芯片型号和调试器3.选择编译器4.项目命名和选择文件路径5.新建成功,给项目添加main.c7.将新建的mainXC16.c文件添加进项目6000000UL这三个就是。

Naiva的博客 451

BUG调试案例一:RK3588+YT8531网络无法PING通调试案例

在使用 RK3588 搭配 YT8531S PHY 芯片进行网络调试时,遇到了“网络无法 Ping 通”的棘手问题。排查了两天,终于找到问题原因。为了避免大家在类似项目中走弯路,也为了加深自己对调试细节的理解,我们特意整理了本次问题的完整排查过程。本篇文章将围绕以下四个方面展开分享: 问题现象&描述 调试过程&分析 问题根源定位 注意事项提醒 举一反三(走两步)

案例文章,高速信号 2336

7-8 求一元二次方程 (10分)

编程求解一元二次方程ax^2 + bx + c = 0的根,要求a、b、c从键盘输入。 要求Main类中必须有如下方法:` public static void main(String[] args);//主方法 public static int solveQuadratic(double[] eqn, double[] roots);//eqn存储输入的三个系数a、b、c,然后将两个实数根存储进roots中,该方法返回实数根的个数。 输入格式: 从键盘输入一元二次方程的三个系数的值(均为实型数),可以

CHINA_wangdasha的博客 2520

RagFlow专题三、RagFlow 关键技术(向量数据库、文档分块、Prompt 设计与召回排序优化)

FAISS 是由 Meta(Facebook)开源的高效向量检索库,适用于大规模向量搜索任务。,并了解了如何通过 RagFlow 机制优化信息检索和生成质量。(FAISS、Milvus、ES)用于高效存储和检索语义向量。提高 LLM 生成效果,增强 RagFlow 任务质量。(分块)策略,将文档拆分成更小的片段,提高检索效率。提高检索精准度,避免文本过长导致信息丢失。提升检索结果的相关性,提高生成质量。当多个检索结果被返回时,我们需要一个。在前一篇文章中,我们详细探讨了。在 RagFlow 任务中,

xiaoqi270620903的专栏 3040

设计递归函数竟然这么简单!

本文来自“天狼啸幽月”的投稿,已获独家授权关于设计递归函数,个人有一点总结和心得,和大家分享一下。从一个简单的例子开始#include"stdio.h" intfun(intn)//求1+2+3+…+n的结果 { if(n==1) return1; returnn+fun(n-1); } intmain(void) ...

码农翻身 8815

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

递归函数详解

文章目录1. 什么是递归函数2. 递归求阶乘3. 递归的进入4. 递归的退出5. 递归的条件 1. 什么是递归函数 一个函数在它的函数体内调用它自身称为递归调用,这种函数称为递归函数。执行递归函数将反复调用其自身,每调用一次就进入新的一层,当最内层的函数执行完毕后,再一层一层地由里到外退出。 一句话总结递归:自我调用且有完成状态 2. 递归求阶乘 举个例子,我们来计算阶乘n! = 1 x 2 x 3 x ... x n,用函数factorial(n)表示,可以看出: 所以,factorial(n)

Lianuuu的博客 2万+

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

递归函数

递归 递归就是一个函数在它的函数体内调用它自身。执行递归函数将反复调用其自身,每调用一次就进入新的一层。递归函数必须有结束条件。 注: 递归的时候,每次调用一个函数,计算机都会为这个函数分配新的空间,这就是说,当被调函数返回的时候,调用函数中的变量依然会保持原先的值,否则也不可能实现反向输出。 #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> //递归 void test(int num) { if (num == 1) { printf

m0_53157173的博客 6634

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

利用递归函数实现阶乘

通过递归函数等三种方式实现阶乘

anni5211314的博客 1万+

帮助大家理解一下递归函数的返回值...

如题: 递归函数往往可以简化我们的代码,尤其是对树的遍历和利用回溯算法写代码的时候,但是递归函数的返回值往往是困扰我们的。 总体来说,我们先要理解函数的调用过程,函数调用过程会用栈来保存函数的返回值和过程,而递归函数就是调用自身函数的过程,所以也是用栈存储,这样就比较容易理解了。 下面一段代码可以帮助大家理解递归函数的返回值。 1 package test; 2 3

code_mover的博客 8507

c语言递归函数为什么要返回,递归函数返回值的有关问题

递归函数返回值的问题前几天写了个哈西表的程序,里面用到的递归。由于是看着书上的算法写的,虽然程序的功能实现了,可关于递归还是有些不懂。然后我回家敲些关于递归函数的程序,发现其中存在好奇妙的关系,下面是我的代码和编译后的截图,希望和大神交流一下经验。#includeintmain(){intdigui(inti);inti;scanf("%d",&i);i=digui(i);prin...

weixin_28676983的博客 1540

解决Python递归函数返回空值问题

Problems from Factorization 要求写一个质因数分解的函数,虽然问题不复杂,但碰到了一些疑惑 在最开始的情况 def IsPrimer(num): for i in range(2, int(num**0.5)+1): if num % i == 0: return False return True fl ...

qq_44124301的博客 1833

python函数:递归函数详解

本文介绍了什么是递归函数,递归函数需要符合什么条件以及递归函数的常见案例的使用。

2403_86719076的博客 2050

如何写递归函数

递归函数,是指某一函数内部自己直接或间接地调用自己,即直接递归和间接递归。是语言中比较高级的技术用法。 递归函数之所以难,是因为是一种过于抽象化的技术,写代码的时候无法直观的看出逻辑是否符合自己要求,因此想一次性写好递归函数,是一件很困难的事情,必须要程序运作起来执行递归函数的代码才能看出是否正确,而且进行测试的难度也很高,有时的隐含bug可能要软件上线后才会渐渐体现出来。 笔者写过几次较为复

鹏霄万里展雄飞 8594

Python 递归函数返回值为 None 的解决办法

在使用 Python 开发的过程中,避免不了会用到递归函数。但递归函数的返回值有时会出现意想不到的情况。 下面来举一个例子: >>> def fun(i): ... i += 1 ... if i < 5: ... fun(i) ... else: ... return i ... >>> r = fun(0) >>> print(r) 比如上面这段代码,乍一看没什么问题,但返回值并不是我们

AlwaysBeta 的专栏 7374

python 递归函数返回值

python递归函数返回值 以下是用递归实现有序数组的二分查找Python代码 def binarysearch(seq, x, lower = 0, upper = None):     if upper == None: upper = len(seq) -  1     middle = (lower + upper) / 2     if x == seq[middle]:  

csdn364747071的博客 4678

58.Python的递归函数

如果一个函数调用了自己,那我们称这个函数为递归函数。

weixin_63986098的博客 1671

递归函数的编写方法

递归函数的编写步骤 1.找到并设置迭代单体 2.设置结束条件 3.编程实现 递归函数简单来说是一种自身调用自身的函数。递归函数可用于需要重复操作的程序,如绘制分形树,下面将以分形树绘制作为递归函数的实例,解释递归函数的编写方法。 1.找到并设置迭代单体 在绘制分形树的过程中,若能先完成分形树中元素的绘制,则可通过迭代操作完成整个分形树的绘制,每一步迭代所进行的操作在此定义为“迭代单体”。每次迭代操...

weixin_43157453的博客 4170
上一篇: 用topcoder准备cs 面试
下一篇: Longest Substring Without Repeating Characters 最长不重复字符的字串 @LeetCode
chiiis
博客等级 码龄14年 422粉丝 429原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值