Professional Documents
Culture Documents
UNIT II – Part I
Acknowledgments
The following individuals have been acknowledged for their contributions to this course material by
Uttaranchal University in Dehradun, India:
Patron Patron
Shri Jitender Joshi Prof. (Dr.) Satbir Sehgal
Chancellor, Uttaranchal University Vice President, Uttaranchal University
Patron Patron
Prof. (Dr.) Dharam Buddhi Prof. (Dr.) Rajesh Bahuguna
Vice-Chancellor, Uttaranchal University Pro Vice-Chancellor, Uttaranchal University
Unit II
1.1. Recursion
The idea behind recursion is to break down a complex problem into smaller, simpler
sub-problems that can be solved more easily. By calling the function again with the sub-
problems, we can solve the original problem step by step. A key aspect of recursion is that it
must eventually reach a base case, which stops the recursive calls and returns a solution. If the
base case is not reached, the function will continue calling itself indefinitely, resulting in an
infinite loop.
Recursion can be useful for solving problems that have a repetitive or recursive nature,
such as tree traversal, calculating factorials, and generating fractal patterns. However, it is
important to understand the limitations of recursion, as it can be difficult to understand and
debug, and can also lead to performance issues if not implemented correctly.
#include <stdio.h>
int factorial(int n) {
if (n == 0) {
} else {
int main() {
int n = 5;
return 0;
Tail Recursion: This is a type of recursion where the last statement in the function is a recursive
call. The benefit of tail recursion is that the recursive call can be optimized by the compiler
into a loop, which eliminates the need for a new stack frame and can result in faster and more
efficient code.
Head Recursion: This is a type of recursion where the first statement in the function is a
recursive call. The function performs some processing before making the recursive call, which
makes it more challenging to optimize. In head recursion, each call to the function creates a
new stack frame, which can result in slower and less efficient code if the recursion is too deep.
It is important to note that some programming languages, such as Scheme and Common Lisp,
support tail call optimization for all forms of recursion, including head recursion. However,
not all programming languages support tail call optimization, and in some cases, it may be
necessary to manually convert head recursion to tail recursion in order to optimize the code.
C programming language does not have built-in support for tail call optimization, which means
that both tail and head recursion will create new stack frames for each call, potentially leading
to stack overflow issues. This means that in C, recursion should generally be used with caution,
as it can be easy to write a program that goes into an infinite loop or exhausts the stack space.
It is often recommended to use iteration instead of recursion whenever possible, as it is typically
faster and more efficient in C.
However, in certain cases, such as when solving problems with a repetitive or recursive
structure, recursion can still be a useful and elegant solution, and it is possible to write recursive
algorithms in C that are safe and efficient. It is just important to be aware of the limitations and
potential performance issues of recursion in C, and to design and implement the algorithm
carefully to avoid stack overflow and other issues.
Recursion is a powerful concept in computer science and has a wide range of applications.
Some common examples include:
1. Mathematical computations: Recursion can be used to solve mathematical problems,
such as finding the factorial of a number, calculating the Fibonacci sequence, or solving
the Tower of Hanoi puzzle.
2. Tree data structures: Recursion is often used to traverse and manipulate tree data
structures, such as binary trees, search trees, and decision trees.
3. File and directory operations: Recursion can be used to perform operations on file
systems, such as traversing a directory hierarchy, searching for files, or copying a
directory structure.
4. Graph algorithms: Recursion can be used to solve problems related to graph theory,
such as finding the shortest path in a graph, or performing depth-first or breadth-first
search.
5. Backtracking: Recursion can be used for backtracking algorithms, such as finding all
possible solutions to a problem, or searching for a specific solution by exploring all
possible paths in a problem space.
6. Divide and conquer algorithms: Recursion can be used to implement a divide and
conquer algorithm, where a large problem is divided into smaller sub-problems that can
be solved recursively, and then combined to solve the original problem.
These are just a few examples of the many applications of recursion in computer science. A
recursion is a versatile tool that can be used in many different domains and can simplify the
solution to many complex problems.
The Tower of Hanoi is a classical problem in computer science, and it is often used to
demonstrate the concept of recursion. The problem involves three rods and a number of disks
of different sizes, which can slide onto any rod. The objective of the puzzle is to move the
entire stack to another rod, obeying the following simple rules:
1. To avoid accidental disc swapping, you can only move one disc at a time.
2. Each move is made by taking the top disc from one of the stacks and putting it on top
of another stack or on an empty rod.
3. No bigger disc can go on top of a smaller one.