[Detailed explanation of function recursion]


Tip: After the article is written, the table of contents can be automatically generated. For how to generate it, please refer to the help document on the right.

1. What is recursion?

Recursion is a topic that cannot be avoided when learning C language functions. So what is recursion?
Recursion is actually a method of solving problems. In C language, recursion means that the function calls itself.
Write the simplest C language recursive code in history:

#include <stdio.h>
int main()
{
    
    
 printf("hehe\n");
 main();//main函数中⼜调⽤了main函数
 return 0;
}

The above is a simple recursive program, but the above recursion is only to demonstrate the basic form of recursion, not to solve the problem. The code will eventually fall into dead recursion, causing stack overflow.
Insert image description here

Recursive thinking:
Convert a large complex problem into a sub-problem similar to the original problem but smaller in scale to solve; until the sub-problem can no longer be split, the recursion ends. So the recursive way of thinking is the process of reducing big things into small ones.
In recursion, recursion means recursion , and recursion means regression< The meaning of /span> will be understood slowly next.

2. Restrictions on recursion

When writing recursion, there are two necessary conditions:

There are restrictions on recursion. When these restrictions are met, the recursion will no longer continue.
Each recursive call gets closer and closer to this limit.

In the following example, we gradually understand these two constraints.

3. Recursive example

3.1 Example 1: Find the factorial of n

Calculate the factorial of n (without considering overflow). The factorial of n is the cumulative multiplication of numbers from 1 to n.

3.1.1 Analysis and code implementation

We know the formula of the factorial of n: n! = n ∗ (n − 1)!
Insert image description here
This idea is to convert a larger problem into a problem that is similar to the original problem but smaller in scale.

n!—> n*(n-1)!
(n-1)! —> (n-1)*(n-2)! a>

No more disassembly until n is 1 or 0

Let’s do a little analysis. When n<=1, the factorial of n is 1, and the factorial of the other n can be calculated through the above formula.
The recursive formula of the factorial of n is as follows:
Insert image description here
Then we can write the function Fact to find the factorial of n. Suppose Fact(n) is to find the factorial of n, Then Fact(n-1) is to find the factorial of n-1. The function is as follows:
Insert image description here
Drawing deduction:
Insert image description here
Insert image description here

3.2 Example 2: Print each digit of an integer sequentially

Input an integer n and print each digit of the integer in order.
If n is a single digit, each digit of n is n itself. If n is more than 1 digit, each digit must be split.

1234%10 will get 4, and then 1234/10 will get 123, which is equivalent to removing 4
Then continue to 123%10, you will get 3, and then divide Remove 3 from 10, and so on
Continue the %10 and \10 operations until every digit of 1234 is obtained;
But there is a problem here. The resulting numbers are in reverse order

But we got inspiration. We found that the lowest digit of a number is actually the easiest to get. It can be obtained through %10
Then let’s assume we want to write a function Print to print Each bit of n is expressed as follows:

Print(n)
If n is 1234, it is expressed as
Print(1234) //Print each digit of 1234 Print(1234) can be split into two steps:
Among them, 4 in 1234 can be obtained through %10, then

  1. Print(1234/10) //Print each digit of 123
  2. printf(1234%10) //Print 4
    After completing the above 2 steps, printing of each digit of 1234 is completed
    Then Print (123)

By analogy, we have

Print(1234)
==>Print(123) + printf(4)
==>Print(12) + printf(3)
==>Print(1) + printf(2)
==>printf(1)

When the printed number becomes a single digit, there is no need to split anymore and the recursion ends.
Code demonstration:
Insert image description here
Function operation process: Insert image description here
In this problem-solving process, we used Making big things smallThe idea
Disassemble Print(1234) to print each bit of 1234 into Print(123) to print 123 first For each digit, print the obtained 4
and disassemble Print(123) to print each digit of 123. First, Print(12) prints each digit of 12, and then print the obtained 3 until Print What is printed is a single digit, just print it directly.

4. Recursion and iteration

Recursion is a good programming technique, but like many techniques, it can also be misused. Just like Example 1-
, when you see the derived formula, it is very confusing. Easily written in recursive form:
Insert image description here

int Fact(int n)
{
    
    
 if(n<=0)
   return 1;
 else
   return n*Fact(n-1);
}

The Fact function can produce correct results, but there is some runtime overhead involved in the recursive function call.

Every time a function is called in C language, it is necessary to apply for a memory space in the stack area for this function call to save the function The values ​​of various local variables during the call. This space is called the runtime stack, or the function stack Frame.

If the function does not return, the stack frame space corresponding to the function will always be occupied. Therefore, if there is a recursive call in the function call, each recursive function call will open up its own stack frame space until the function recursion no longer continues and starts to return. Release stack frame space layer by layer.

Therefore, if you use function recursion to complete the code, if the recursion level is too deep, too much stack frame space will be wasted, and it may also cause stack over flow problems.
Code demonstration:
Insert image description here
So if you don’t want to use recursion, you have to think of other methods, usually iteration method (usually the loop method).
For example: calculating the factorial of n can also produce the cumulative multiplication of numbers from 1 to n.
Insert image description here
The above code can complete the task, and the efficiency is better than the recursive method.
In fact, many of the problems we see are explained in recursive form simply because it is clearer than the non-recursive form, but iterative implementations of these problems are often more efficient than recursive implementations higher.

When a problem is too complex to be solved iteratively, the simplicity of the recursive implementation can compensate for the runtime overhead.

Summarize

Okay, this blog ends here. If you have a better point of view, please leave a message in time. I will watch it carefully and learn from it.
If you don’t accumulate steps, you can’t reach a thousand miles; if you don’t accumulate small streams, you can’t become a river or sea.

Guess you like

Origin blog.csdn.net/2301_79585944/article/details/133936316