Recursive depth combat

Source: Internet
Author: User

First of all, let's start with a simple recursive small example to feel:

Inverse of the string:

#include <stdio.h>//recursive string inversion void reverse (char* s) {    if ((s! = NULL) && (*s! = ')})    {        reverse (s + 1);                printf ("%c", *s);}    } int main (int argc, char *argv[]) {      reverse ("12345");    printf ("\ n");  printf ("Press ENTER to continue ...");  GetChar ();  return 0;}
Run:


First understand the stack when the function is called:

1. In fact, the "function call stack" in the program is an application of the stack data structure.

2. The function call stack is typically increased from high address to low address

1> the bottom of the stack is the high address of the memory

2> stack top is memory low address

3. the data stored in the function call stack is the active record


Give a simple example of a call to a complete program:



Stack in the program:

1. The stack space in the program can be seen as an application of a sequential stack

2. The stack holds the required maintenance information for a function call

1> function parameter, function return address

2> Local Variables

3> Function Call Context

3. The program stack space is essentially a sequential stack

4. Access to the program stack space is performed through a function call

5. The program stack space still adheres to the LIFO rule

Now go back and analyze the procedure and the stack in the program for the functions in the program above:


First: The function starts from the main, the bottom of the stack is the active record of the main function, and then executes to the reverse function, the bottom of the stack will save the activity record of the reverse function, the parameters stored in the reverse activity record are s--> "12345", so * s stands for 1;

Then judge the reverse function inside the IF statement inside the condition or for the true, continue to call themselves recursively, this time will be on the stack to create a new activity record, which is (s+1)-and "2345", *s represents 2; Then continue to judge whether the conditions inside the IF statement are satisfied.

Continue to call yourself recursively, *s represents 3

......

Continue to call yourself recursively, *s represents 5

Continuing to invoke itself recursively, *s points to ' + ', the inability to satisfy the condition means that recursion is not possible, which means that this recursive call is over. After the recursive call ends, it means that the stack is retired. The fallback is meant to pull a log from the top of the stack, pop up to recover the last call, from the above figure can be seen in the previous call contains two statements, one of which is the printf statement. So first output a 5 (*s point 5), and then continue to withdraw the stack, reverse call after the end of the printf () statement, so printed out a 4 (*s point 4); Continue to rewind the stack, pop up the top of the activity record ... And so on, so the results output "54321". Isn't it magical.

Here's an easy-to-read blog post on the Web: http://chengengjie.blog.163.com/blog/static/1263313972013216105710595/

Similar to the above-mentioned process, can be compared to see.


The following begins the recursive depth combat:

recursive definition: The program itself calls itself a programming technique called recursion. Recursion has direct recursion and indirect recursion

1. Direct recursion: The function calls itself during execution

2. The function calls other functions during execution and passes through the function call itself

Four properties of recursion:

1. There must be a final termination condition (the F-Judgment statement of I in the program above), or the program will enter an infinite loop

2. Sub-problem is smaller than the original problem on the scale or closer to the termination condition

3. Sub-problem can be solved by recursive call again or by satisfying termination condition

4. Sub-problem solution should be able to combine the solution of the whole problem, compared with the above simple small routine to see, that's it!

The mathematical idea of recursion:

1. Recursion is a mathematically divided and autonomous thought

2. Recursion transforms large and complex problems into the same but smaller problems to deal with the original problem

3. Recursion requires a boundary condition, and when the boundary condition is not satisfied, recursion continues, and when the boundary conditions are met, the recursion stops.

It is very important to solve the problem by recursion first to establish a recursive model. (data structures and algorithms to the back of the tree and graph algorithm will be heavily used in recursion)

Demo1: Recursive method of Fibonacci sequence

Fibonacci Sequence Description (not very clear can go to the left turn to find Niang ...) )

1 2 3 4 5 6 ... (indicates number of items)

1 1 2 3 5 8 ... , you can see the Fibonacci sequence of an = An-1 + An-2; here A1 = 1; For the sake of calculation it is convenient to define the No. 0 item A0 = 0; Compare the above recursive definitions and examples to see if the recursive conditions are met! That is, an can be resolved to the original problem An-1 + An-2 to solve, and then An-1 = An-2 + an-3,an-2 = An-3 + An-4, and then turn to the same as the original problem, but smaller. At the same time the recursive relationship, there are boundary conditions A1 = 1,a0 = 0; So it's easy to write a program.

Fibonacci sequence recursion Solution #include <stdio.h>int Fibonacci (int n) {    if (n > 1)//First is recursive n = = 1 and N = = 0 Boundary conditions can also be put in front     {        R Eturn Fibonacci (n-1) + Fibonacci (n-2);    }    else if (n = = 1)    {        return 1;    }    else if (n = = 0)    {        return 0;    }} int main () {    int i = 0;        for (I=1; i<=10; i++)    {        printf ("Fibonacci (%d) =%d\n", I, Fibonacci (i));    }        printf ("Press ENTER to continue ...");    GetChar ();    return 0;}
Run:



Demo2:strlen Recursive solution

Strlen Recursive solution #include <stdio.h>int strlen (const char* s) {    if (s = = NULL)//Incoming parameter legitimacy judgment     {        return-1;    }    else if (*s = = ') '//Boundary condition     {        return 0;    }    else    {        return strlen (s+1) + 1;//establishes a recursive model, and the above string reversal model resembles     }}int main () {    printf ("strlen (\" 12345\ ") =% D\n ", strlen (" 12345 "));    printf ("strlen (NULL) =%d\n", strlen (null));    printf ("strlen (\" \ ") =%d\n", strlen (""));//empty string         printf ("Press ENTER to continue ...");    GetChar ();    return 0;}

Run:


The recursive model of the two problems is relatively simple, the following begins to increase the difficulty gradually a little

Demo3: Hanoi Recursive solution

Problem Model:

There are a, B, c three pillars, first assume that there are three different sizes on the pillar a plate, and the small plate always can only be placed on the top of the big plate , and now to use pillar B to move the tray on the top of the plate on the pillar C and after the removal of C pillars on the small plate always on the top of the plate At any one time during the removal process, the small plate must always be placed on top of the large plate (and, of course, a tray can be placed on a pillar).

Analysis builds a recursive model:




Eventually it becomes the result we want.

For the above moving graph summary: Move 3 plates, the problem can be broken down into three steps:

First step: Move two

Step two: then move a to C directly

Step three: move two more

This translates the problem of moving three disks into a two-disk move! Isn't it amazing! (Two moving in a different destination) but the method of recursion has come out.

Boundary conditions: the second step in the first step of the revelation, when the move two disk, a in a only one disk can be directly moved to the point A in the C-pillar, which is equivalent to the recursive boundary, that is, when we want to move the number of plates of 1, it is possible to move directly from the starting point to the destination!

That means there's a recursive relationship now! Transform the big problem of moving three plates into a small problem of moving two plates! So how do you solve the problem of moving two plates? The big question of moving two plates is sure to translate into a small problem of moving a plate! And the small problem of moving a plate is done directly! Plus boundary conditions! Ok! Hanoi's recursive model is not enlightened!

Here is a detailed explanation of the three steps of the operation:

A is the starting pillar B is the auxiliary pillar C as the end pillar

A pillar has three plates to be moved to the C pillar with the help of B pillars (the above rules are to be followed during the move)

Then the first step: Move the two plates on the start a pillar to the end B pillar with the C pillar (step one)

Step Two: Start a column moves directly to the end of the C pillar (second step on the chart)

Step three: Move the two plates on the start B pillar to the end C pillar with a pillar (step three)

Hanoi Recursive solution #include <stdio.h>//n represents the number of plates on a pillar, A is the starting column, B is the auxiliary pillar, and C is the purpose pillar void Hanoi (int n, char A, char B, char c) {    if ( n > 0)    {        if (n = = 1)//boundary condition when there is only one plate, direct a moves to C         {            printf ("%c\n", A, c);        }        else        {            //against the diagram above, the first step is to decompose the problem and move the plate on the start a pillar to B             Hanoi (N-1, A, C, b) with C;                         In contrast to the above illustration, the second step is to move the plate from the start a pillar directly to C             printf ("%c-%c\n", A, c);                        In contrast to the above analysis, the third step is to move the two plates on the starting B pillar to the end C pillar with a pillar             Hanoi (N-1, B, A, c);}}    int main () {    Hanoi (4, ' A ', ' B ', ' C ');    Hanoi (8, ' A ', ' B ', ' C ');        printf ("Press ENTER to continue ...");    GetChar ();    return 0;}
Run:


Isn't it amazing! You can look at the paper on the move to try to see if that's the case! Recursive weight in the mind, in the end it is appropriate to use recursion depends on the problem of the transition to a recursive definition, whether a problem can be recursive thinking to solve the problem!


Demo4: A recursive solution for all permutations

First understand the full permutation definition: any m (m≤n) elements from n different elements, arranged in a certain order, is called an arrangement of extracting m elements from n different elements. All permutations are called when m=n.

For a small example: for a three character sequence A, B, c its full array of ABC, ACB, BCA, BAC, CAB, CBA six kinds

Analyze the problem and set up recursive thinking: for the full arrangement of 3 different elements, can we imagine if we could find the full array of three elements by asking for the full permutation of the two elements? Then the recursion can not be the whole arrangement of an element to find the full array of two elements? And the whole arrangement of an element is very good, that is, the element itself! In other words, the whole permutation of an element is the critical point of recursion (boundary condition), so what we are looking for now is the recursive relationship (also said that the three elements of the whole arrangement how and two elements of the entire arrangement together), then how to find recursive relations?
If P (a,b,c) is required to be fully arranged, it is only necessary to lift a out of P (b,c), (A,p (B,c)), (that is, the entire arrangement of the a,b,c can be transformed by a proposed first, to find the full arrangement of P (b,c))

( b,p (a,c)),(C,p (A, b) ) ...

The whole arrangement of P (B,C) can be made by B first to ask for the whole arrangement of C, and C is the whole arrangement of C itself! Then put C to ask for the full array of B!

From the small example above, it can be seen that the number of occurrences of each element in the first position in a, B, and C is evenly distributed (6/3 = 2), which is 2 times





 Full permutation recursive solution #include <stdio.h>//three parameters to be perfection permutation character array start position B, end position e void permutation (char s[], int b, int e) {if (0 <=        b) && (b <= e))//legality detection {if (b = = e) {printf ("%s\n", s);            } else {int i = 0; The first element is carried out first, and then the remainder of the elements perfection arranged for (i=b; i<=e; i++) {//swap, each time I put the element I first position, and then the first position of the element                          Place the first I position char C = s[b]; S[B] = s[i];//loop needs to carry each element in the array to the first position once s[i] = c;//the same as the one that the cache is carrying out//start position has been fixed a dollar                Permutation (S, b+1, E);//to the rest of the whole arrangement//according to the analysis of the above just once the whole arrangement is finished, we get only part of the result                 For example, the whole arrangement of ABC, the cycle of a to get out, only to out of the ABC ACB two but there are other//such as, so first to restore the sequence to maintain the original order and then in the next for the next element in the loop to carry out                The following three lines are swapped back to let the elements in the array or keep the ABC order c = S[b];                S[B] = s[i];            S[i] = c; }}}}int Main () {CHAR s[] = "ABCD";        Permutation (s, 0, 3);    printf ("Press ENTER to continue ...");    GetChar (); return 0;}

Run:


Other conditions can be measured on their own! found that if the idea of recursive model, the idea of a step-by-step understanding, write a recursive algorithm to solve the problem is not so difficult! Of course this problem is not very difficult! But still learned a new way of thinking!


Recursion and backtracking

1. Recursion is also often used in programming applications where backtracking algorithms are required

2. The basic idea of backtracking algorithm: (Exhaustive search algorithm)

1> from a certain state of the problem, search for all the states that can be reached

2> when a state arrives, it can be rolled forward and continue searching for other reachable states

3> when all states are reached, the backtracking algorithm ends

3. The function Activity object can be used to save the state data of the backtracking algorithm in the program design, so we can use recursion to complete the backtracking algorithm.

4. Backtracking algorithm is an important occasion for recursive application, while the active object using function call can save important variable information in backtracking algorithm, recursion is an important way to realize the backtracking algorithm!!!


Demo5: The Eight Queens question

Problem Description: On a 8*8 chess plate, there are 8 queens, each queen occupies a lattice, requires the Queen does not appear to each other "attack" phenomenon, that is, no two queens can be on the same line, the same column or the same diagonal. How many ways are there to ask? Board such as:



The first step simulates the board: 8*8 's chessboard can be modeled with a 8*8 two-dimensional array

The second step to the board to put the Queen: How to put it? How do you put it?

Here's one step at a-one-step analysis solution:


For the position in (I,J), the problem begins with the Queen from the top down line of the put, so for the position (I, J) can put the Queen only need to consider the above three directions up to the border there are no other queens! If there are no other queens in the three directions to the boundary, then the (i, j) position can be placed on a queen. Instead, it's not. The offsets for each of the positions in each direction of the three directions on the graph are ( -1,-1), (-1, 0), (-1, 1), respectively (a direction array, with only three elements in it), in relation to (I, j). The rest is how to keep looking.

Algorithm ideas:

1. Initialization: i = 1

2. Initialization: j = 1

3. From line I, restore the current value of J to determine the J position

A. Position J can be placed in Queen: Mark position (I,J), i++, go to step 2

B. Position J not fit Queen: J + +, go to step A,

C. When J > 8 o'clock, I--, turn step 3 (backtracking)

4. End: Line 8th There is a place to put the Queen to find a solution exit this recursive print

Look directly at the code!

 The eight Queens problem recursive solution #include <stdio.h> #define N 8//defines a struct representing the offset of a typedef struct _tag_pos{int ios;//i The offset of the int jos;//j Offset} pos;static char board[n+2][n+2]; Simulate 8*8 's checkerboard plus up and down boundary static Pos pos[] = {{-1,-1}, {-1, 0}, {-1, 1}};//directional struct array static int count = 0;//global variable used to count how many methods Voi    D init ()//initialize checkerboard {int i = 0;        int j = 0; for (i=0; i<n+2; i++)//Build the chessboard boundary, with "#" for {board[0][i] = ' # ';//No. 0 line Board[n+1][i] = ' # ';//N+1 line Bo        Ard[i][0] = ' # ';    Board[i][n+1] = ' # '; } for (I=1; i<=n; i++)//Middle 8*8 checkerboard all initialized to space {for (j=1; j<=n; J + +) {Board[i][j] = '    ';//Space is available}}}void display ()//used to print two-dimensional array {int i = 0;        int j = 1;        for (i=0; i<n+2; i++) {for (j=0; j<n+2; J + +) {printf ("%c", Board[i][j]);    } printf ("\ n");    }}int Check (int i, int j)//If there are no queens in three directions (I, j) This position can be put a new queen {int ret = 1;        int p = 0; for (p=0; p<3; p++)//two-layer loop outer loop indicates direction     {int ni = i;                int NJ = j; If the RET is true and does not touch the border, continue while (Ret && (BOARD[NI][NJ]! = ' # '))//If no queen continues until the boundary is reached {ni =            NI + Pos[p].ios;                        NJ = NJ + pos[p].jos; RET = RET && (BOARD[NI][NJ]! = ' * ');//This is denoted by "*" for Queen} return ret;}        void find (int i)//row lookup on line I find {int j = 0;                if (i > N)//If the search has been more than the eighth line, the description has been found, recursive export {count++;                printf ("Solution:%d\n", count);                Display ();    GetChar ();             } else {for (j=1; j<=n; j + +)//Line I from the first position to find {if (check (i, j))//If the current position can put the Queen                  {Board[i][j] = ' * ';//Then put a queen//the following sentence after a recursive call will find that the local variables running in the program are stored in the activity record of the function call Find (i+1);//Look for the next line//recursion after the end of the representative position (I, j) may be put queen or may not put queen,//So first Empty, continue to find the next line, see the shadow does not affect the next queen, do not affect in the first//(for example, there is a situation, bitSet (I,J) put the Queen to cause the next line 8 positions can not put) board[i][j] = ";    }}}}int Main () {init ();    Find (1);//start with printf from the first line ("press ENTER to continue ...");    GetChar (); return 0;}

Run:


At last, I can choose some of them to draw on the paper to look at it is not! Recursive, minimalist and not simple!

Spent two hours after work in the spare time to learn the recursive knowledge to re-review the discovery or learned a lot of things! Although it took time to spend less than 5 hours, but their understanding of recursion further deepened! Today I am a step closer to the great God!




Recursive depth combat

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.