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

理解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




相机通用类之海康相机,软触发硬触发(飞拍),并输出halcon格式对象 如何显示图像:可以访问我文章开头的博客,通过编写相机通用类即可,程序中是有继承通用类,通过访问相机通用的获取图像数据,从而传输图像数据。具体可以查看相机通用类。整体过程其实比较简单,由于海康相机没有像一些品牌相机一样可以直接使用序列号开启相机,所以我们需要通过对相机信息进行索引,根据索引到的相机序列号来开启相机。 阅读详情

相关推荐

银河麒麟(桌面版/服务器版)远程桌面配置全攻略:XRDP与VNC实战指南

本文提供了银河麒麟操作系统(桌面版与服务器版)配置远程桌面的完整实战指南。详细对比并演示了XRDP与VNC两种主流方案的安装、配置与连接步骤,涵盖从环境准备、软件安装、服务启动到客户端连接的全过程,并针对常见的黑屏、连接失败等问题给出了有效的排坑解决方案,帮助用户实现跨平台的便捷图形化远程管理。

b0c1d2的博客 810

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

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

系统 运维 939

PX4自定义uORB消息与MAVLink消息映射实战:从飞控到QGC地面站完整流程解析

本文详细解析PX4飞控中自定义uORB消息与MAVLink消息映射的完整流程,涵盖从飞控内部消息定义、MAVLink消息创建到QGC地面站接收显示的全链路实践。重点介绍如何使用mavlink inspector工具进行调试,解决版本兼容性和多实例消息处理等常见问题,为无人机开发者提供可靠的实时数据监控方案。

ll5678的博客 1067

递归

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

n 512

OPC UA 协议详解

OPC UA(统一架构)是新一代工业自动化标准通信协议,替代传统OPC Classic,具有跨平台、高安全性、标准化等优势。基于TCP协议,支持全平台部署,采用面向对象架构组织数据,提供实时读写、事件订阅、历史数据访问等功能。作为工业4.0核心协议,适用于智能制造、数字孪生等场景,能实现多品牌设备统一接入。相比Modbus和MQTT,OPC UA协议更规范安全但复杂度较高,是大型工业集群互联的主流选择。

eastyuxiao的专栏 726

Cesium教程(十七):淹没分析

淹没分析是根据某片区域的地形及洪水流量速度,动态模拟该地形区域水位逐渐上涨的淹没过程。该功能可适用于山区、丘陵等地形起伏较大区域,模拟洪水涨到安全限定高度的淹没过程,为防洪水救灾提供一定的参考。此外,还可以为河谷地带修建水利工程设计与选址提供参考依据。

WwLK123的博客 3008

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

C++经典面试题100例及答案

答:把一些具有共性的对象归类后形成一个集合,也就是所谓的类。答:这样可以提高编译效率,因为分开的话只需要编译一次生成对应的.obj文件后,再次应用该类的地方,这个类就不会被再次编译,从而大大的提高了编译效率。答:这种函数会自动为内联函数,这种函数在函数调用的地方在编译阶段都会进行代码替换。答:常对象是指在任何场合都不能对其成员的值进行修改的对象。答:所谓的回调函数,就是预先在系统的对函数进行注册,让系统知道这个函数的存在,以后,当某个事件发生时,再调用这个函数对事件进行响应。

usstmiracle的博客 3万+

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

FPGA实现串口升级及MultiBoot(五)通过约束脚本添加IPROG实例

上一篇文章种总结了MultiBoot 关键技术,分为:一个指令、二种位流、三种方式、四样错误。针对以上四句话我们接下来详细分析。在开始解析之前我们先准备两个文件,一个是控制LED闪烁的文件,通过更换引脚约束可以控制不同LED,这样就可以指示是启动MultiBoot位流还是Golden位流。还有一个文件就是uart发送文件,会指示启动的位流格式和启动地址。文件都比较简单,就不列举了,文件详见文后的链接。对于 IPROG 指令目前有三种实现方式,分别为:1)通过约束脚本添加;2)通过ICAPE2原语

OpenFPGA的博客 2104

【Unity 实用工具篇】✨| I2 Localization 实现本地化及多种语言切换,快速上手

Unity的多语言本地化是一个很实用的功能,它可以帮助游戏支持多种语言,让不同语言的玩家都能够更好地体验游戏。 而实现本地化的方案也有很多种,各个方案之间也各有优劣,后面也会对多个方案进行介绍学习。 本文就来介绍一个专门作用于多语言本地化的插件:I2 Localization 。

努力前行,总会成为自己心中的那道光 3万+

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

台球 PCOL:极致物理还原的网页斯诺克引擎(附源码深度解析)

*完整源码地址**:[https://github.com/billiards/pcol-core](https://github.com/billiards/pcol-core)(包含详细文档与示例)通过这个项目,我们不仅创建了一个游戏,更构建了一个**可扩展的物理引擎框架**,为网页端复杂物理模拟开辟了新的可能性。**在线体验**:[https://pcol.billiards](https://pcol.billiards)(支持移动端触控操作)clone.velocity.x *= -0.92;

Loving_enjoy的博客 2797

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

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

码农翻身 8815

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

递归函数详解

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

Lianuuu的博客 2万+

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

递归函数

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

m0_53157173的博客 6634

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

利用递归函数实现阶乘

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

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、付费专栏及课程。

余额充值