Today, let's talk about recursive ideas. Sometimes recursion can make ourAlgorithmEasier to understand andCodeThe amount is also greatly reduced. For example
For the tree's "first, middle, and last" traversal, let's see how simple and easy it is to use recursion to describe this problem.
1 # Region First-order traversal of Binary Trees
2 /// <Summary>
3 /// First-order traversal of Binary Trees
4 /// </Summary>
5 /// <Typeparam name = "T"> </typeparam>
6 /// <Param name = "Tree"> </param>
7 Public Void Bintree_dlr <t> (chaintree <t> tree)
8 {
9 If (Tree = Null )
10 Return ;
11
12 // First output the root element
13 Console. Write (tree. Data + " \ T " );
14
15 // Then traverse the left subtree
16 Bintree_dlr (tree. Left );
17
18 // Finally, traverse the right subtree
19 Bintree_dlr (tree. Right );
20 }
21 # Endregion
22
23 # Region Central traversal of Binary Trees
24 /// <Summary>
25 /// Central traversal of Binary Trees
26 /// </Summary>
27 /// <Typeparam name = "T"> </typeparam>
28 /// <Param name = "Tree"> </param>
29 Public Void Bintree_ldr <t> (chaintree <t> tree)
30 {
31 If (Tree = Null )
32 Return ;
33
34 // Traverse left subtree first
35 Bintree_ldr (tree. Left );
36
37 // Then the output Node
38 Console. Write (tree. Data +" \ T " );
39
40 // Finally, traverse the right subtree
41 Bintree_ldr (tree. Right );
42 }
43 # Endregion
44
45 # Region Post-order traversal of Binary Trees
46 /// <Summary>
47 /// Post-order traversal of Binary Trees
48 /// </Summary>
49 /// <Typeparam name = "T"> </typeparam>
50 /// <Param name = "Tree"> </param>
51 Public Void Bintree_lrd <t> (chaintree <t> tree)
52 {
53 If (Tree = Null )
54 Return ;
55
56 // Traverse left subtree first
57 Bintree_lrd (tree. Left );
58
59 // Then traverse the right subtree
60 Bintree_lrd (tree. Right );
61
62 // Final output node Element
63 Console. Write (tree. Data + " \ T " );
64 }
65 # Endregion
Let's see how concise and clear it is. Of course, recursion can be changed to non-recursion, but it is not concise and easy to understand.
I. Concept
Recursion: To put it bluntly, it is a method that calls itself directly or indirectly. It converts the problem to a subproblem of small scale, and then uses multiple recursion until the result can be obtained.
And then return the call layer by layer through the explain solution to finally obtain the solution of the entire problem. In short, recursion can be summarized as one sentence: "If you do not enter the system, the system will return ".
Ii. Three Elements
<1> In recursion, each cycle must narrow down the problem.
<2> every two steps of recursive operations are closely related. For example, in the "return operation" of "recursion", the previous output is the last input.
<3> when the scale of a subproblem is small enough, you must be able to directly find the solution to the scale problem. In fact, you must have the condition for ending recursion.
Iii. Note
<1> As mentioned earlier, recursion must have a recursive exit.
<2> deep recursion involves frequent stack-to-stack and memory allocation. Therefore, the operation efficiency is relatively low. It is not recommended when the problem is large.
<3> During the recursion process, parameters, method return points, and local variables in each call are stored in the stack. If the problem occurs at a large scale, Stack Overflow may occur.
4. Two examples
<1> I believe that everyone has learned factorial in junior high school, for example, 5! = 5*4*3*2*1
Idea: Based on the factorial features above, we can easily export n! = N * (n-1) * (n-2)... * 2*1,
N! = N * (n-1 )! ,
(N-1 )! = (N-1) * (n-2 )!.
Obviously, he satisfies the three elements of recursion. When n is not large, we can use recursion to win it.
1 Static Void Main ( String [] ARGs)
2 {
3 While (True )
4 {
5 // Factorial Problem
6 Console. writeline ( " \ N enter a number to calculate the factorial: " );
7
8 Int Num = Int . Parse (console. Readline ());
9
10 Console. writeline ( " \ N factorial result: " + Fact (Num ));
11 }
12 }
13
14 Static Int FACT ( Int N)
15 {
16 If (N = 1 )
17 Return 1 ;
18
19 Return N * fact (n- 1 );
20 }
First time: enter 5 to get the correct result.
The second time: when the input is 10, we can find out as many as 3.62 million. It can be seen that the time complexity of our team is n !, ThatProgramThe game is over,
Third time: the input value is 100, which has exceeded Int. maxvalue,
The fourth time: enter 10 W to bring out the famous "stack overflow". Good guy, we know that "recursion" is stored in the program in the form of "stack, the Return Value of the method in each "recursion"
Parameters in functions are stored in the stack. The stack space allocated by each thread in C # is 1 MB. Therefore, when n is very large, the stack will be cracked.
<2> when we were at the top of the computer culture, we were exposed to the "hexadecimal conversion problem", for example, converting "decimal" to "binary".
Idea: divide the remainder by two, take the remainder as the bitwise of the corresponding binary number, and then divide it by the quotient to get the next low position ....... when the last Division operator is 0, the highest bitwise of binary is obtained,
For example, (100) 10 = (1100100) 2. if you carefully analyze this problem, you will find that it meets the three elements of "recursion,
① In hexadecimal conversion, the data scale will be reduced.
② When the quotient is 0, it is the exit of recursion.
So we can use recursion to solve this problem.
Static Void Main ( String [] ARGs)
{
Console. writeline ( " Enter a decimal number: " );
Int Num = Int . Parse (console. Readline ());
String Result = String . Empty;
Console. writeline ( " The converted binary is: " + Converttobinary ( Ref Result, num ));
Console. Readline ();
}
Static String Converttobinary ( Ref String STR, Int Num)
{
// Delivery Process
If (Num = 0 )
Return String . Empty;
Converttobinary ( Ref STR, num/ 2 );
// Process of returning
Return STR + = (Num %2 );
}