Recursion and tail recursion (C language)

Source: Internet
Author: User

In the field of computer science, recursion is implemented by recursive functions. The programming technique called by the program itself is called recursion (recursion).

A procedure or function has a method of directly or indirectly invoking itself in its definition or description, which usually transforms a large and complex problem layer into a smaller problem similar to the original problem, and the recursive strategy can describe the repeated computations needed in the process of solving the problems by a small number of programs. Greatly reduces the code volume of the program. The ability to recursion is to define an infinite set of objects with limited statements.

In general, recursion is required: boundary conditions, recursive forward segments, and recursive return segments.

Recursion advances when boundary conditions are not met, and returns recursively when the boundary conditions are met.

Attention:

(1) Recursion is the invocation of itself in a process or function;

(2) When using a recursive strategy, there must be a definite recursive end condition called a recursive exit.

This article address: http://www.cnblogs.com/archimedes/p/rescuvie-tailrescuvie.html, reprint please indicate source address.

Basic recursion

Problem: Calculating n!

The mathematical formula is: n! =nx (n-1) x (n-2) ... 2x1

Using recursion, you can define:

Calculate 4 in a recursive way!

F (4) =4XF (3) Recursion phase

F (3) =3XF (2)

F (2) =2xf (1)

F (1) =1 termination conditions

F (2) = (2) x (1) Regression phase

F (3) = (3) x (2)

F (4) = (4) x (6)

24 Recursive completion

Implement the factorial function recursively:

int fact (int  n) {    if0)        return0 ;     Else if 0 1 )        return1;     Else        return 1 );}

Here's a detailed analysis of how recursion works

Take a look at the execution of functions in C language, need to know some about the C program in the storage of the organization, basically an executable program consists of 4 regions: code snippet, static data area, heap, stack

Code snippet: Contains machine instructions executed by the program when it is run.

Static data area: Contains data that has persisted throughout the program's life cycle. E.g global variables and static local variables

Heap: Contains the storage space that is dynamically allocated when the program runs. E.g memory allocated with malloc

Stack: contains function call information.

The growth direction of the heap grows from low address to high address, while the stack is growing in the opposite direction (the actual situation is related to CPU architecture)

When a function is called in a C program, a space is allocated in the stack to hold the information associated with the call, and each invocation is considered active. The storage space on the stack is called an active record or a stack frame.

The stack frame consists of 5 regions: Input parameters, return value space, temporary storage space used to evaluate expressions, state information saved at function calls, and output parameters, see:

Stacks are a great solution for storing function call information, but the stack has some drawbacks:

The stack maintains the information for each function call until the function returns, which takes a considerable amount of space, especially in cases where many recursive calls are used in the program. In addition, because there is a lot of information that needs to be saved and restored, it takes time to generate and destroy active records. We need to consider an iterative approach. Fortunately, we can use a special recursive approach called tail recursion to avoid the aforementioned drawbacks.

Tail recursionDefined

If all the recursive calls in a function appear at the end of the function, we call this recursive function the tail recursion. This recursive invocation is the tail recursion when the recursive call is the last executed statement in the body of the function and its return value is not part of an expression. The feature of the tail recursive function is that it is not necessary to do anything in the regression process , which is important because most modern compilers use this feature to automatically generate optimized code.

Principle

When the compiler detects that a function call is tail-recursive, it overwrites the current activity record instead of creating a new one in the stack. The compiler can do this because the recursive call is the last statement to be executed during the current active period, so there is nothing else to do in the stack frame when the call returns, so there is no need to save the stack frame. By overwriting the current stack frame instead of adding one on top of it, the stack space used is greatly reduced, which makes the actual running efficiency even higher. Although the compiler can optimize the stack overflow problem caused by tail recursion, in programming, we should try to avoid the appearance of tail recursion, because all the tail recursion can be replaced by a simple goto loop.

Instance

To understand how the tail recursion works, let's calculate the factorial again in recursive form. First of all, it can be very easy to understand why the recursion previously defined is not a tail recursion. Recall the definition of computational n!: Calculate n times (n-1) in each active period, let n=n-1 and continue the process until n=1. This definition is not tail-recursive, because the return value for each active period relies on the return value of n multiplied by one of the following active periods, so the stack frame that is generated for each call will have to be saved on the stack until the return value of the next child call is determined. Now let's consider defining the process of calculating n! in the form of tail recursion.

This definition also needs to accept the second parameter A, which is not much different. A (initialized to 1) maintains the depth of the recursive hierarchy. This allows us to avoid having to multiply the return value by n again every time. However, in each recursive call, make A=na and n=n-1. Continue the recursive call until the n=1, which satisfies the end condition, returns a immediately.

The code example gives a C function Facttail, which takes an integer n and computes the n! in the form of a tail recursion. This function also accepts a parameter a,a with an initial value of 1. Facttail uses a to maintain the depth of the recursive hierarchy, except that it is similar to fact. Readers can look at the similarities between the implementation of the function and the definition of the tail recursion.

intFacttail (intNinta) {    if(N <0)        return 0; Else if(n = =0)        return 1; Else if(n = =1)        returnA; Else        returnFacttail (N-1Na);}

The function in the example is tail-recursive, because a single recursive call to Facttail is the last statement executed before the function returns. It happens that the last statement in Facttail is also a call to Facttail, but this is not required. In other words, there are other statements that can be executed after a recursive call, except that they can only be executed if the recursive call is not executed.

The tail recursion is extremely important, without the tail recursion, the stack consumption of the function is difficult to estimate, need to save many intermediate functions of the stack. such as f (n, sum) = f (n-1) + value (n) + sum; The N function call stack is saved, and tail recursion f (n, sum) = f (n-1, Sum+value (n)) is used; This preserves only the last function stack, which can be optimized for deletion.

There may be many exceptions in C, but the programming language is not only the C language, but in the functional language Erlang (also the stack language), if you want to maintain the high concurrency of the language, you must replace the traditional recursion with the tail-recursive return.

Recursion and tail recursion (C language)

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.