-
-
Notifications
You must be signed in to change notification settings - Fork 211
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #43 from pavitraag/main
Added sorting and recursive algorithms
- Loading branch information
Showing
7 changed files
with
1,104 additions
and
0 deletions.
There are no files selected for viewing
168 changes: 168 additions & 0 deletions
168
docs/algorithms/Recursive Algorithms/DirectRecursion.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,168 @@ | ||
--- | ||
id: direct-recursion-algo | ||
sidebar_position: 1 | ||
title: Direct Recursion | ||
sidebar_label: Direct Recursion | ||
--- | ||
|
||
### Definition: | ||
|
||
Direct recursion is when a function calls itself directly. The function keeps calling itself with a modified argument until a base case is met, which stops the recursion. Direct recursion is used to solve problems that can be broken down into smaller, similar subproblems. | ||
|
||
### Characteristics: | ||
|
||
- **Self-Calling Function:** | ||
- A function is directly recursive if it calls itself within its own body. | ||
|
||
- **Base Case:** | ||
- A base case is required to stop the recursive calls, preventing infinite recursion. | ||
|
||
- **Multiple Calls:** | ||
- The function may call itself once or multiple times depending on the problem. | ||
|
||
### Time Complexity: | ||
|
||
- **Time Complexity: O(n)** | ||
The time complexity of direct recursion depends on the problem. For simple problems like calculating a factorial, it usually takes linear time `O(n)` where `n` is the input size. | ||
|
||
### Space Complexity: | ||
|
||
- **Space Complexity: O(n)** | ||
Each recursive call takes up space on the call stack, leading to a space complexity proportional to the depth of the recursion. | ||
|
||
### Example Problems: | ||
|
||
1. **Factorial Function:** | ||
|
||
The factorial of a number `n` is defined as `n! = n * (n-1) * (n-2) * ... * 1`. We can calculate the factorial using direct recursion. | ||
|
||
```cpp | ||
#include <iostream> | ||
using namespace std; | ||
|
||
int factorial(int n) { | ||
if (n <= 1) return 1; // Base case | ||
return n * factorial(n - 1); // Recursive call | ||
} | ||
|
||
int main() { | ||
int num = 5; | ||
cout << "Factorial of " << num << " is " << factorial(num) << endl; | ||
return 0; | ||
} | ||
``` | ||
- In this example, the function `factorial()` calls itself until `n` becomes 1, which is the base case. | ||
2. **Sum of First N Natural Numbers:** | ||
We can use direct recursion to find the sum of the first `n` natural numbers. | ||
```cpp | ||
#include <iostream> | ||
using namespace std; | ||
int sum(int n) { | ||
if (n == 0) return 0; // Base case | ||
return n + sum(n - 1); // Recursive call | ||
} | ||
int main() { | ||
int n = 10; | ||
cout << "Sum of first " << n << " natural numbers is " << sum(n) << endl; | ||
return 0; | ||
} | ||
``` | ||
|
||
- In this example, the function `sum()` calls itself, reducing the value of `n` by 1 at each step until it reaches 0, the base case. | ||
|
||
3. **Fibonacci Sequence:** | ||
|
||
The Fibonacci sequence is a series where each number is the sum of the two preceding ones, starting with 0 and 1. We can compute the nth Fibonacci number using direct recursion. | ||
|
||
```cpp | ||
#include <iostream> | ||
using namespace std; | ||
|
||
int fibonacci(int n) { | ||
if (n <= 1) return n; // Base cases | ||
return fibonacci(n - 1) + fibonacci(n - 2); // Recursive calls | ||
} | ||
|
||
int main() { | ||
int n = 5; | ||
cout << "Fibonacci of " << n << " is " << fibonacci(n) << endl; | ||
return 0; | ||
} | ||
``` | ||
- Here, the function `fibonacci()` calls itself twice to compute the Fibonacci numbers for `n-1` and `n-2`. | ||
### Recursive Tree: | ||
Direct recursion often generates a recursion tree, where each function call spawns new calls, visualizing the branching structure of recursive calls. | ||
### Common Applications: | ||
- Factorial calculation | ||
- Fibonacci sequence | ||
- Tower of Hanoi | ||
- Sum of a series | ||
- Tree traversal | ||
### C++ Implementation: | ||
**Factorial Example (Direct Recursion)** | ||
```cpp | ||
#include <iostream> | ||
using namespace std; | ||
int factorial(int n) { | ||
if (n <= 1) return 1; // Base case | ||
return n * factorial(n - 1); // Recursive call | ||
} | ||
int main() { | ||
int num = 5; | ||
cout << "Factorial of " << num << " is " << factorial(num) << endl; | ||
return 0; | ||
} | ||
``` | ||
|
||
**Sum of First N Natural Numbers (Direct Recursion)** | ||
```cpp | ||
#include <iostream> | ||
using namespace std; | ||
|
||
int sum(int n) { | ||
if (n == 0) return 0; // Base case | ||
return n + sum(n - 1); // Recursive call | ||
} | ||
|
||
int main() { | ||
int n = 10; | ||
cout << "Sum of first " << n << " natural numbers is " << sum(n) << endl; | ||
return 0; | ||
} | ||
``` | ||
**Fibonacci Example (Direct Recursion)** | ||
```cpp | ||
#include <iostream> | ||
using namespace std; | ||
int fibonacci(int n) { | ||
if (n <= 1) return n; // Base case | ||
return fibonacci(n - 1) + fibonacci(n - 2); // Recursive call | ||
} | ||
int main() { | ||
int n = 5; | ||
cout << "Fibonacci of " << n << " is " << fibonacci(n) << endl; | ||
return 0; | ||
} | ||
``` | ||
|
||
### Summary: | ||
|
||
Direct recursion is a simple yet powerful tool for solving problems that involve repetitive or self-similar subproblems. The key challenge lies in identifying the base case to prevent infinite recursion and understanding the problem well enough to break it down recursively. |
184 changes: 184 additions & 0 deletions
184
docs/algorithms/Recursive Algorithms/IndirectRecursion.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,184 @@ | ||
--- | ||
id: indirect-recursion-algo | ||
sidebar_position: 2 | ||
title: Indirect Recursion | ||
sidebar_label: Indirect Recursion | ||
--- | ||
|
||
### Definition: | ||
|
||
Indirect recursion occurs when a function calls another function, and eventually, the second function calls the first function back. This process forms a cycle of function calls between two or more functions, instead of a single function calling itself directly. | ||
|
||
### Characteristics: | ||
|
||
- **Mutual Call:** | ||
- In indirect recursion, two or more functions call each other in a cyclic manner. | ||
|
||
- **Base Case:** | ||
- Each recursive cycle must include a base case to prevent infinite loops and ensure termination. | ||
|
||
- **Multiple Functions:** | ||
- Indirect recursion involves more than one function. A function calls another, which in turn calls the first one back. | ||
|
||
### Time Complexity: | ||
|
||
- **Time Complexity: O(n)** | ||
- The time complexity of indirect recursion depends on the number of recursive calls. For simple problems, it is typically linear `O(n)`. | ||
|
||
### Space Complexity: | ||
|
||
- **Space Complexity: O(n)** | ||
- Each recursive call uses stack space, leading to a space complexity proportional to the depth of the recursion. | ||
|
||
### Example Problems: | ||
|
||
1. **Odd and Even Numbers:** | ||
|
||
In this example, we use two functions: one for checking even numbers and another for odd numbers. The function `isEven()` calls `isOdd()`, and `isOdd()` calls `isEven()` until the base case is reached. | ||
|
||
```cpp | ||
#include <iostream> | ||
using namespace std; | ||
|
||
bool isEven(int n); | ||
bool isOdd(int n); | ||
|
||
bool isEven(int n) { | ||
if (n == 0) return true; // Base case | ||
return isOdd(n - 1); // Call isOdd | ||
} | ||
|
||
bool isOdd(int n) { | ||
if (n == 0) return false; // Base case | ||
return isEven(n - 1); // Call isEven | ||
} | ||
|
||
int main() { | ||
int num = 5; | ||
if (isEven(num)) { | ||
cout << num << " is even." << endl; | ||
} else { | ||
cout << num << " is odd." << endl; | ||
} | ||
return 0; | ||
} | ||
``` | ||
- Here, `isEven()` calls `isOdd()`, and `isOdd()` calls `isEven()`. This continues until the base case is met. | ||
2. **Mutually Recursive Functions:** | ||
Another classic example of indirect recursion is mutually recursive functions, where one function calls another, and the second function calls the first function back in a loop. | ||
```cpp | ||
#include <iostream> | ||
using namespace std; | ||
void functionA(int n); | ||
void functionB(int n); | ||
void functionA(int n) { | ||
if (n > 0) { | ||
cout << "In Function A: " << n << endl; | ||
functionB(n - 1); // Call functionB | ||
} | ||
} | ||
void functionB(int n) { | ||
if (n > 0) { | ||
cout << "In Function B: " << n << endl; | ||
functionA(n / 2); // Call functionA | ||
} | ||
} | ||
int main() { | ||
int num = 10; | ||
functionA(num); // Start the recursion chain | ||
return 0; | ||
} | ||
``` | ||
|
||
- In this example, `functionA()` calls `functionB()`, and `functionB()` calls `functionA()`. The base case for each function ensures termination. | ||
|
||
### Recursive Tree: | ||
|
||
Just like direct recursion, indirect recursion forms a recursion tree. However, the branches of this tree involve multiple functions that call each other in cycles. Each function call is part of a chain, leading back to earlier calls. | ||
|
||
### Applications: | ||
|
||
Indirect recursion is often used in: | ||
- State machines | ||
- Parsing algorithms | ||
- Handling mutually exclusive conditions (like odd/even checks) | ||
|
||
### Common Challenges: | ||
|
||
- **Tracking Function Calls:** | ||
- Indirect recursion can be more challenging to understand and debug because multiple functions are involved, and keeping track of the flow of execution can be complex. | ||
|
||
- **Base Case Design:** | ||
- Designing appropriate base cases for each function in the recursion cycle is crucial to ensure that the recursion terminates. | ||
|
||
### C++ Implementation: | ||
|
||
**Odd and Even Checker (Indirect Recursion)** | ||
```cpp | ||
#include <iostream> | ||
using namespace std; | ||
|
||
bool isEven(int n); | ||
bool isOdd(int n); | ||
|
||
bool isEven(int n) { | ||
if (n == 0) return true; // Base case | ||
return isOdd(n - 1); // Call isOdd | ||
} | ||
|
||
bool isOdd(int n) { | ||
if (n == 0) return false; // Base case | ||
return isEven(n - 1); // Call isEven | ||
} | ||
|
||
int main() { | ||
int num = 5; | ||
if (isEven(num)) { | ||
cout << num << " is even." << endl; | ||
} else { | ||
cout << num << " is odd." << endl; | ||
} | ||
return 0; | ||
} | ||
``` | ||
**Mutually Recursive Functions (Indirect Recursion)** | ||
```cpp | ||
#include <iostream> | ||
using namespace std; | ||
void functionA(int n); | ||
void functionB(int n); | ||
void functionA(int n) { | ||
if (n > 0) { | ||
cout << "In Function A: " << n << endl; | ||
functionB(n - 1); // Call functionB | ||
} | ||
} | ||
void functionB(int n) { | ||
if (n > 0) { | ||
cout << "In Function B: " << n << endl; | ||
functionA(n / 2); // Call functionA | ||
} | ||
} | ||
int main() { | ||
int num = 10; | ||
functionA(num); // Start the recursion chain | ||
return 0; | ||
} | ||
``` | ||
|
||
### Summary: | ||
|
||
Indirect recursion occurs when two or more functions call each other in a cycle. It's an important concept in recursive algorithms, but it can be harder to follow due to the involvement of multiple functions. The base cases for each function in the cycle must be carefully designed to ensure the recursion terminates. |
Oops, something went wrong.