C language allows functions to call themselves, which is called recursion. When many people first learn recursion, they are often confused by layers of nested calls. They don't know how to call them? Now let's use a small example to demonstrate how the function works when it is called recursively.
void up_and_down(int n) { printf("---- Level %d: n location 0x%p \r\n",n,&n); if(n<4) up_and_down(n + 1); printf("**** Level %d: n location 0x%p \r\n",n,&n); } int main() { up_and_down(1); system("pause"); return 0; }
First, call the function to assign a value of 1 to N, then add 1 to n when n is less than 4, and then continue to call this function. Exit the function until the value of n is greater than 4. The running results are as follows:
It can be seen from the print results that the value of n increases successively from 1, 2, 3 and 4, then decreases successively from 4, 3, 2 and 1, and finally exits the program. What is the execution process of this program? Let's use a picture to analyze it.
The following is a step-by-step analysis:
First, n=1, execute the first print statement in the function body. Then execute the if statement. Since the current value of n is 1 and less than 4, call the function itself to pass the value of 1 + 1 to the function.
Next, execute the first print statement in the function body. Then execute the if statement. Since the current value of n is 2 and less than 4, call the function itself to pass the value of 2 + 1 to the function.
Continue executing the first print statement in the function body. Then execute the if statement. Since the current value of n is 3 and less than 4, call the function itself to pass the value of 3 + 1 to the function.
Continue executing the first print statement in the function body. Then execute the if statement. Since the current value of n is 4 and not less than 4, the if condition is not tenable and up will not be called again_ and_ The down () function, but executes the last print statement in the function body. When the print statement is executed, exit the function. Since the fourth function is from the third function call, after exiting the fourth function, the program will return to the place where the third function calls it.
After the fourth function exit, it is equivalent to returning to the up of the third function_ and_ down(3 + 1); At this position, since the function has been executed, the code continues to execute and print the print statement of the last line.
Similarly, when the function called for the third time is completed, the program will return to the calling location, that is, to the function called for the second time.
The program returns to up_and_down(2 + 1); After this statement, continue to execute the print statement of the last line. When the print statement of the last line is completed, the function called for the second time will return to the place where it was called, that is, to the interior of the function called for the first time.
The program returns to up_and_down(1 + 1); After this statement, continue to execute the print statement of the last line. When the print statement of the last line is completed, the program returns to the place where the function was first called. The first call to this function is in the main () function, so the program will return to the main () function. Because there are no other statements executed in the main() function. So the whole process of the program is over.
It can also be seen from the printing results that the printing statements of the first line in the function body are printed first. The printing statements of the last line in the function body will not continue until the four function calls are completed. It can also be seen from the address of N. every time a function is called, n will re apply for an address, and then release the applied address when the function exits.
It can be seen that the recursive function is still a waste of memory space when executing. For the single chip microcomputer with limited resources, it is better to use the recursive function as little as possible. Does recursive function really have no advantage at all? Of course, there are. Through the observation of the above examples, it can be found that the recursive function is executed in the principle of first in and last out. Therefore, it is very convenient to use recursive functions for programs that need flashback execution.
For example, during binary conversion, the first calculated value should be placed in the last bit of the result, and the last calculated value should be placed in the first bit of the result.
For example, now you want to convert 10 to binary numbers. The calculation process is as follows:
10%2 ---- 0
10/2=5
5%2 ----- 1
5/2=2
2%2 ----- 0
2/2=1
1%2 ----- 1
First, divide 10 by 2 to get the remainder. The remainder is 0, then this 0 is the lowest bit of binary conversion. Next, divide 10 by 2 to integer, and then divide the result by 2 to get the remainder. This is the penultimate bit of binary. Install such a rule and calculate it successively until the divisor result is 1
That is, when the passed parameter becomes 1, the recursive call ends. In this way, when 10 is converted to binary, it is 1010, which is just the calculated number flashback arrangement.
This function is realized by recursion
void to_binary(unsigned long n) { int r; r = n % 2; if(n >= 2) to_binary(n/2); putchar(r == 0?'0':'1'); return; } int main() { to_binary(100); printf("\r\n"); system("pause"); return 0; }
Define a function to print binary values. First divide the number by 2 for remainder, then divide the number by 2 for rounding, and then continue to call this function. The operation results are as follows:
Convert 100 to binary value
The results printed by the program are the same as the actual calculation results, indicating that the program function is normal. To facilitate viewing, you can print out the function execution process.
In order to check the function execution efficiency, the function execution time can be printed here.
The test code is as follows:
#include <stdio.h> #include <stdlib.h> #include <time.h> #include <math.h> void to_binary(unsigned long n) { int r; r = n % 2; printf("n-%d,r-%d\r\n",n,r); if(n >= 2) to_binary(n/2); putchar(r == 0?'0':'1'); return; } typedef union _LARGE_INTEGER { struct { long LowPart ;// 4-byte integer long HighPart;// 4-byte integer }; long long QuadPart;// 8-byte integer } LARGE_INTEGER; int main(int argc, char *argv[]) { int i = 0,val = 0; clock_t startTime,endTime; int time = 0; LARGE_INTEGER secondcount= {0}; LARGE_INTEGER startcount= {0}; LARGE_INTEGER stopcount= {0}; QueryPerformanceFrequency(&secondcount); //Gets the number of CPU Performance Tick units per second //Printf ("3: system count frequency is:% d \r\n",secondcount.QuadPart); QueryPerformanceCounter(&startcount); //Timing start to_binary(100); //Recursive call QueryPerformanceCounter(&stopcount); //Timing end time=( ((stopcount.QuadPart - startcount.QuadPart)*1000*1000)/secondcount.QuadPart); printf(" \r\n\r\n Program running time is: %d us\r\n\r\n",time); system("pause"); return 0; }
A test is added here to test the execution time of recursive calling function. The principle of the test is to record the system count value before the function is executed, and then record the system count value after the execution is completed. The difference between the two values is the execution time of the system.
The results are as follows:
It can be seen that it takes 1.163ms to calculate the binary number of 100 at a time, which is too slow for the computer. If you calculate a larger number, it will take more time. Test it with the number of 100000000.
The time spent is about 5.1ms. It can be seen that the larger the number, the deeper the function will be nested, and the more memory will be consumed. The longer the execution time.
When using recursive functions in the future, we must pay attention to the use environment. Otherwise, if a deeply nested recursive function is called on a single chip microcomputer with few resources, it is likely that half of the system resources will be exhausted, resulting in program crash, and it is difficult to find the reason.