Recursion is a powerful tool for designing and describing algorithms. Because it is often used in the description of complex algorithms, we will discuss it before introducing other algorithm design methods.
Algorithms that can use recursive descriptions usually have the following features: To solve the n-scale problem, we try to break it down into smaller-scale problems, then, we can easily construct solutions to big problems from the solutions to these small problems, and these smaller problems can also be decomposed into smaller problems using the same decomposition and synthesis methods, then, we can deconstruct these smaller problems to solve large-scale problems. In particular, when the scale N is 1, it can be directly solved.
[Problem] Write the nth letter for calculating the Fibonacci series
Data fib (n ).
Fibonacci series: 0, 1, 1, 2, 3 ,......, That is:
FIB (0) = 0;
FIB (1) = 1;
FIB (n) = fib (n-1) + fib (n-2) (when n> 1 ).
Recursive functions:
Int fib (int n)
{If (n = 0) return 0;
If (n = 1) return 1;
If (n> 1) return fib (n-1) + fib (n-2 );
}
The execution process of recursive algorithms is divided into two stages: recursive and regression. In the recurrence stage, the solution of more complex problems (scale N) is pushed to the solution of problems that are simpler than the original problem (scale less than N. For example, in the above example, solve fib (N) and push it to solve fib (n-1) and FIB (n-2 ). That is to say, for calculation of Fib (N), FIB (n-1) and FIB (n-2) must be calculated first, while fib (n-1) and FIB (n-2) must be calculated ), the FIB (n-3) and FIB (n-4) must be calculated first ). And so on until the calculation of Fib (1) and FIB (0) can immediately obtain results 1 and 0, respectively. In the recurrence stage, termination of recursion is required. For example, in function fib, when n is 1 and 0.
In the regression phase, after obtaining the solution of the simplest case, return the result step by step and obtain the solution of a slightly complex problem, for example, after obtaining fib (1) and FIB (0, the result of Fib (2) is returned ,......, After obtaining the results of Fib (n-1) and FIB (n-2), the results of Fib (n) are returned.
When writing recursive functions, note that the knowledge of local variables and parameters in the functions is limited to the current call layer. When recursion enters the simple problem layer, parameters and local variables at the original level are hidden. In a series of "simple question" layers, they have their own parameters and local variables.
Due to recursion, a series of function calls and a series of repeated computations may occur, the execution efficiency of recursive algorithms is relatively low. When a recursive algorithm can be easily converted into a recursive algorithm, programs are usually compiled based on the recursive algorithm. For example, for the above example, the function fib (n) of the nth item of the Fibonacci series should adopt a recursive algorithm, that is, the next item is calculated from the first two items of the Fibonacci series, until the required n items are calculated.
[Problem] combination Problem
Problem description: Find the natural numbers 1, 2 ,...... And N. For example, all the combinations of N = 5 and r = 3 are: (1) 5, 4, 3 (2) 5, 4, 2 (3) 5, 4, 1
(4) 5, 3, 2 (5) 5, 3, 1 (6) 5, 2, 1
(7) 4, 3, 2 (8) 4, 3, 1 (9) 4, 2, 1
(10) 3, 2, 1
The ten combinations listed in the analysis can be used to consider the algorithm of the composite function. Set the function to void comb (int m, int K) to find the natural numbers 1, 2 ,...... And any combination of K numbers in M. When the first number of a combination is selected, the following number is a combination of the number of K-1 from the remaining number of m-1. In this way, the combination problem of K number in M number is transformed into the combination problem of the number of K-1 in M number. Let the function introduce the working array a [] to store the numbers of the obtained combinations. The Convention function places the first number of the K numeric combinations in a [K, after a combination is obtained, a combination in a [] is output. The first number can be m m-1 ,...... , K, the function puts the first number of the definite combination into the array, there are two possible options, because the remaining elements of the combination have not been removed, continue to recursively determine; or, because all elements of the combination have been determined, the combination is output. For details, see the function comb in the following program.
[Program]
# Include <stdio. h>
# Define maxn100
Int A [maxn];
Void comb (int m, int K)
{Int I, J;
For (I = m; I> = K; I --)
{A [k] = I;
If (k> 1)
Comb (I-1, k-1 );
Else
{For (j = A [0]; j> 0; j --)
Printf ("% 4D", a [J]);
Printf ("/N ");
}
}
}
Void main ()
{A [0] = 3;
Comb (5, 3 );
}
[Problem] backpack Problems
Problem description: N items with different values and weights are selected from the N items, so that the total weight of the selected item does not exceed the specified weight limit, but the total value of the selected item is the largest.
Set the weight of N items to w0, W1 ,... , Wn-1, item values are v0, V1 ,... Vn-1. Use recursive item search options. The preceding multiple options are available, and the solution with the largest total value is retained in the array option []. The total value of the solution is stored in the variable maxv. The new scheme is being investigated, and the item selection is saved in the array COP []. Assuming that the current scheme has taken into account the items of the previous I-1, it is now necessary to take into account item I; the sum of the weight of the items included in the current scheme is TW; so far, if other items are selected as possible, the expected value of the total value of this solution is TV. When TV is introduced to an algorithm, once the expected value of the total value of the current scheme is smaller than the total value of maxv in the preceding scheme, it is necessary to continue to investigate the meaningless work of the current scheme and terminate the current scheme, check the next solution immediately. Because the total value of the solution is no larger than that of maxv, this solution will not be further investigated. This also ensures that the solution found after the function is better than the previous solution.
There are two possible options for the I-th item:
(1) considering that item I is selected, this possibility is feasible only when it does not exceed the total weight limit of the solution. After selection, continue to recursively consider the selection of other items.
(2) consider that item I is not selected. This possibility is only when item I is not included, and a more valuable solution may be found.
Write the recursive algorithm as follows:
Try)
{/* Consider the possibility that item I is included in the current plan */
If (including item I is acceptable)
{Include item I in the current plan;
If (I <n-1)
Try (I + 1, TW + item I weight, TV );
Else
/* Another complete solution, because it is better than the previous solution and uses it as the best solution */
Save the current scheme as the temporary best scheme;
Restore the exclusive state of item I;
}
/* Consider the possibility that item I is not included in the current plan */
If (excluding items I can only be considered by male)
If (I <n-1)
Try (I + 1, TW, TV-item I value );
Else
/* Another complete solution, because it is better than the previous solution, uses it as the best solution */
Save the current scheme as the temporary best scheme;
}
To understand the preceding algorithm, we recommend the following examples. There are four items. their weight and value are shown in the table:
Item 0 1 2 3
Weight 5 3 2 1
Value 4 4 3 1
And set the weight to 7. The above algorithm indicates the process of finding the solution. From the graph, once a solution is found, the algorithm is further improved. If it can be determined that a search branch does not find a better solution, the algorithm does not continue to search for the branch, but immediately terminates the branch and examines the next branch.
Compile functions and programs based on the above algorithms as follows:
[Program]
# Include <stdio. h>
# Define n 100
Float limitw, maxv;
Float totv = 0;
Int option [N], COP [N];
Struct {
Float weight;
Float value;
} A [n];
Int N;
Void find (int I, float TW, float TV)
{
Int K;
/* Consider the possibility that item I is included in the current plan */
If (TW + A [I]. weight <= limitw)
{
COP [I] = 1;
If (I <n-1) Find (I + 1, TW + A [I]. Weight, TV );
Else
{
For (k = 0; k <n; k ++)
Option [k] = COP [k];
Maxv = TV;
}
COP [I] = 0;
}
/* Consider the possibility that item I is not included in the current plan */
If (TV-A [I]. value> maxv)
If (I <n-1) Find (I + 1, TW, TV-A [I]. value );
Else
{
For (k = 0; k <n; k ++)
Option [k] = COP [k];
Maxv = TV-A [I]. value;
}
}
Void main ()
{
Int K;
Float W, V;
Printf ("input item type/N ");
Scanf ("% d", & N );
Printf ("input the weight and value of each item/N ");
For (totv = 0.0, K = 0; k <n; k ++)
{
Scanf ("% 1f % 1f", & W, & V );
A [K]. Weight = W;
A [K]. value = V;
Totv + = V;
}
Printf ("input restricted weight/N ");
Scanf ("% 1f", & limitw );
Maxv = 0.0;
For (k = 0; k <n; k ++) COP [k] = 0;
Find (0, 0.0, totv );
For (k = 0; k <n; k ++)
If (Option [k]) printf ("% 4D", k + 1 );
Printf ("/n total value %. 2f/N", maxv );
}
In comparison, we will consider non-recursive program solutions using the same solution. In order to increase the search speed, the program does not simply generate all the solutions one by one, but forms a solution worth further consideration from the impact of each item on the solution, A solution is formed by examining each item in sequence. The investigation of item I involves the following situations: when the item is contained in the total weight limit of the solution, the item should be included in the solution; on the contrary, this item should not be included in an ongoing solution. Similarly, when an item is not included in the solution, it is possible to find a better solution than the current temporary solution; if this item is not included in the current solution, you should not continue to consider it. For any scheme worth further consideration, the program will further consider the next item.
[Program]
# Include <stdio. h>
# Define n 100
Float limitw;
Int COP [N];
Struct ele {
Float weight;
Float value;
} A [n];
Int K, N;
Struct {int flg;
Float TW;
Float TV;
} Twv [N];
Void next (int I, float TW, float TV)
{
Twv [I]. flg = 1;
Twv [I]. Tw = TW;
Twv [I]. TV = TV;
}
Float find (struct ele * a, int N)
{Int I, K, F;
Float maxv, TW, TV, totv;
Maxv = 0;
For (totv = 0.0, K = 0; k <n; k ++)
Totv + = A [K]. value;
Next (0, 0.0, totv );
I = 0;
While (I> = 0)
{
F = twv [I]. flg;
Tw = twv [I]. TW;
TV = twv [I]. TV;
Switch (f)
{
Case 1: twv [I]. flg ++;
If (TW + A [I]. weight <= limitw)
If (I <n-1)
{Next (I + 1, TW + A [I]. Weight, TV );
I ++;
}
Else
{Maxv = TV;
For (k = 0; k <n; k ++)
COP [k] = twv [K]. flg! = 0;
}
Break;
Case 0: I --;
Break;
Default: twv [I]. flg = 0;
If (TV-A [I]. value> maxv)
If (I <n-1)
{
Next (I + 1, TW, TV-A [I]. value );
I ++;
}
Else
{Maxv = TV-A [I]. value;
For (k = 0; k <n; k ++)
COP [k] = twv [K]. flg! = 0;
}
Break;
}
}
Return maxv;
}
Void main ()
{Float maxv;
Printf ("input item type/N ");
Scanf ("% d", & N );
Printf ("input restricted weight/N ");
Scanf ("% 1f", & limitw );
Printf ("input the weight and value of each item/N ");
For (k = 0; k <n; k ++)
Scanf ("% 1f % 1f", & A [K]. Weight, & A [K]. value );
Maxv = find (A, N );
Printf ("/N:/N ");
// For (k = 0; k <n; k ++)
// If (Option [k]) printf ("% 4D", k + 1 );
Printf ("/n total value %. 2f/N", maxv );
}