TAIL_RECURSIVE_QUICKSORT(A,p,r)while p<r //Partiton and sort left subarray q = PARTITION(A,p,r) TAIL_RECURSIVE_QUICKSORT(A,p,q-1) p = q+1
From. Http://www.cnblogs.com/Anker/archive/2013/03/04/2943498.html
1. Recursion
We are familiar with the concept of recursion. In simple terms, recursion is a function that calls itself directly or indirectly for direct or indirect recursion. In general, recursion requires boundary conditions, recursive forward segments, and recursive return segments. If the boundary condition is not met, recursive advances. If the boundary condition is met, recursive returns. Note the following when using recursion:(1) recursion is to call itself in a process or function. (2) When using a recursive policy, there must be a clear recursive termination condition called the recursive exit.
Recursion is generally used to solve three types of problems:
(1) data is defined recursively. (Fibonacci function, factorial of N)
(2) The problem solution is implemented recursively. (Backtracking)
(3) The data structure is defined by recursion. (Tree traversal, Graph Search)Disadvantages of recursion: recursive algorithms are less efficient than common algorithms such as ordinary loops. Therefore, we should avoid recursion whenever possible, unless there is no better algorithm or a specific situation, recursion is more appropriate.
During the recursive call process, the system opens a stack for storing the return points and local volumes of each layer. Therefore, excessive recursion times may cause stack overflow.Use linear recursion to implement the Fibonacci function. The program is as follows:
1 int FibonacciRecursive(int n)2 {3 if( n < 2)4 return n;5 return (FibonacciRecursive(n-1)+FibonacciRecursive(n-2));6 }
The code written recursively is very easy to understand. It selects computer steps based on the function conditions. For example, to calculate the value at n = 5, the recursive call process is shown in:
2. tail recursion
As the name implies, tail recursion is calculated from the end, and the corresponding result is calculated every time the recursion is performed. That is to say, function calls appear at the end of the caller's function, because they are at the end, therefore, there is no need to save any local variables. directly let the called function return more than the caller, and return to the caller.Tail recursion is to put the current calculation result (or path) in the parameter and pass it to the lower-level function.Deep functions are not faced with more and more simple problems, but with more and more complex problems, because parameters contain the preceding steps of the operational path.
Tail recursion is extremely important, and does not require tail recursion. The Stack Consumption of functions is immeasurable and the stacks of many intermediate functions need to be saved. For example, F (n, sum) = f (n-1) + value (n) + sum; stores n function call stacks, and uses tail recursion F (n, sum) = f (n-1, sum + value (n); in this way, only the last function stack is retained, and the previous optimization can be deleted.
Use tail recursion to implement the Fibonacci function. The program is as follows:
1 int FibonacciTailRecursive(int n,int ret1,int ret2)2 {3 if(n==0)4 return ret1; 5 return FibonacciTailRecursive(n-1,ret2,ret1+ret2);6 }
For example, to calculate the value at n = 5, the tail recursive call process is shown in:
From the figure, we can see that there is no need to return the result for recursion, but two extra spaces need to be introduced to maintain the current result.
To better understand the application of tail recursion, write a program to practice. The length of a single-chain table is solved using direct recursion and tail recursion. The C language implementation procedure is as follows:
1 # include <stdio. h> 2 # include <stdlib. h> 3 4 typedef struct node 5 {6 int data; 7 struct node * Next; 8} node, * linklist; 9 10 void initlinklist (linklist * head) 11 {12 if (* head! = NULL) 13 free (* head); 14 * head = (node *) malloc (sizeof (node); 15 (* head)-> next = NULL; 16} 17 18 void insertnode (linklist * head, int d) 19 {20 node * newnode = (node *) malloc (sizeof (node )); 21 newnode-> DATA = D; 22 newnode-> next = (* head)-> next; 23 (* head)-> next = newnode; 24} 25 26 // directly recursively calculate the length of the linked list 27 int getlengthrecursive (linklist head) 28 {29 If (Head-> next = NULL) 30 return 0; 31 return (getlengthrecursive (Head-> next) + 1); 32} 33 // calculate the length of the linked list using tail recursion, and save the length of the current linked list using the variable ACC, continue accumulating 34 int getlengthtailrecursive (linklist head, int * ACC) 35 {36 IF (Head-> next = NULL) 37 return * ACC; 38 * ACC = * ACC + 1; 39 return getlengthtailrecursive (Head-> next, ACC); 40} 41 42 void printlinklist (linklist head) 43 {44 node * pnode = head-> next; 45 while (pnode) 46 {47 printf ("% d->", pnode-> data ); 48 pnode = pnode-> next; 49} 50 printf ("-> null \ n"); 51} 52 53 int main () 54 {55 linklist head = NULL; 56 int Len = 0; 57 initlinklist (& head); 58 insertnode (& head, 10); 59 insertnode (& head, 21); 60 insertnode (& head, 14 ); 61 insertnode (& head, 19); 62 insertnode (& head, 132); 63 insertnode (& head, 192); 64 printlinklist (head ); 65 printf ("the length of linklist is: % d \ n", getlengthrecursive (head); 66 getlengthtailrecursive (Head, & Len ); 67 printf ("the length of linklist is: % d \ n", Len); 68 system ("pause"); 69}
Shows the program test results:
Summary of recursion and tail recursion