Skip to content

Commit

Permalink
Merge branch 'AlgoGenesis:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
isnehamondal authored Nov 4, 2024
2 parents abb3be3 + 45fb558 commit fd0b856
Show file tree
Hide file tree
Showing 12 changed files with 891 additions and 0 deletions.
73 changes: 73 additions & 0 deletions Binary Tree/Level Order Traversal/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# Binary Tree Level Order Traversal in C

This project contains a C program that constructs a binary tree from user input and performs a level order traversal (breadth-first traversal) using a queue. Each level's nodes are printed on a new line.

## Algorithm

1. **Build Tree**: Starting with the root node, ask the user to input values for each node.
- For each node, take user input to determine its left and right children.
- If the input is `-1`, that child is considered `NULL` (no node).
2. **Level Order Traversal**:
- Initialize a queue to hold nodes at each level.
- For each node in the queue:
- Print the node’s value.
- Add its left and right children to the queue (if they exist).
- Each level is printed on a new line.

---

## Approach Using Queues

The program uses a queue to facilitate the level order traversal. The algorithm follows a breadth-first approach, where nodes are visited level-by-level:

1. Start by enqueuing the root node.
2. For each node:
- Dequeue it and print its value.
- Enqueue its left child (if present).
- Enqueue its right child (if present).
3. Repeat until the queue is empty. Each level is printed line by line, indicating level-based traversal.

---

## Complexity Analysis

### Time Complexity

- **Tree Construction**: \(O(n)\), where \(n\) is the number of nodes. Each node is visited once.
- **Level Order Traversal**: \(O(n)\), as each node is dequeued, printed, and its children (if any) are enqueued once.

### Space Complexity

- **Tree Construction**: \(O(n)\) for storing nodes in the binary tree.
- **Queue for Traversal**: \(O(w)\), where \(w\) is the maximum width of the binary tree, which in the worst case could be \(O(n)\) if the tree is perfectly balanced.

---

## Sample Input and Output

### Example

Here’s a sample input and output for the program:

**Input:**
Enter root node value (or -1 for NULL): 1
Enter left child of 1 (or -1 for NULL): 2
Enter right child of 1 (or -1 for NULL): 3
Enter left child of 2 (or -1 for NULL): 4
Enter right child of 2 (or -1 for NULL): 5
Enter left child of 3 (or -1 for NULL): 6
Enter right child of 3 (or -1 for NULL): 7
Enter left child of 4 (or -1 for NULL): -1
Enter right child of 4 (or -1 for NULL): -1
Enter left child of 5 (or -1 for NULL): -1
Enter right child of 5 (or -1 for NULL): -1
Enter left child of 6 (or -1 for NULL): -1
Enter right child of 6 (or -1 for NULL): -1
Enter left child of 7 (or -1 for NULL): -1
Enter right child of 7 (or -1 for NULL): -1

**Output:**
Level Order Traversal:
1
2 3
4 5 6 7
131 changes: 131 additions & 0 deletions Binary Tree/Level Order Traversal/program.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
#include <stdio.h>
#include <stdlib.h>

struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
};

// Helper function to create a new tree node
struct TreeNode* createNode(int val) {
struct TreeNode* newNode = (struct TreeNode*)malloc(sizeof(struct TreeNode));
newNode->val = val;
newNode->left = NULL;
newNode->right = NULL;
return newNode;
}

// Queue structure for holding TreeNode pointers
struct Queue {
struct TreeNode** data;
int front, rear, size, capacity;
};

// Function to create a queue of given capacity
struct Queue* createQueue(int capacity) {
struct Queue* queue = (struct Queue*)malloc(sizeof(struct Queue));
queue->capacity = capacity;
queue->front = queue->size = 0;
queue->rear = capacity - 1;
queue->data = (struct TreeNode**)malloc(queue->capacity * sizeof(struct TreeNode*));
return queue;
}

// Check if the queue is full
int isFull(struct Queue* queue) {
return queue->size == queue->capacity;
}

// Check if the queue is empty
int isEmpty(struct Queue* queue) {
return queue->size == 0;
}

// Function to add an item to the queue
void enqueue(struct Queue* queue, struct TreeNode* item) {
if (isFull(queue)) return;
queue->rear = (queue->rear + 1) % queue->capacity;
queue->data[queue->rear] = item;
queue->size = queue->size + 1;
}

// Function to remove an item from the queue
struct TreeNode* dequeue(struct Queue* queue) {
if (isEmpty(queue)) return NULL;
struct TreeNode* item = queue->data[queue->front];
queue->front = (queue->front + 1) % queue->capacity;
queue->size = queue->size - 1;
return item;
}

// Function to build a tree by taking user input
struct TreeNode* buildTree() {
int val;
printf("Enter root node value (or -1 for NULL): ");
scanf("%d", &val);

if (val == -1) return NULL;

struct TreeNode* root = createNode(val);
struct Queue* queue = createQueue(100); // Adjust size as needed
enqueue(queue, root);

while (!isEmpty(queue)) {
struct TreeNode* current = dequeue(queue);

// Left child
printf("Enter left child of %d (or -1 for NULL): ", current->val);
scanf("%d", &val);
if (val != -1) {
current->left = createNode(val);
enqueue(queue, current->left);
}

// Right child
printf("Enter right child of %d (or -1 for NULL): ", current->val);
scanf("%d", &val);
if (val != -1) {
current->right = createNode(val);
enqueue(queue, current->right);
}
}

free(queue->data);
free(queue);
return root;
}

// Function to perform level order traversal
void levelOrder(struct TreeNode* root) {
if (!root) return;

struct Queue* queue = createQueue(100); // Adjust size as needed
enqueue(queue, root);

while (!isEmpty(queue)) {
int levelSize = queue->size;

for (int i = 0; i < levelSize; ++i) {
struct TreeNode* node = dequeue(queue);
printf("%d ", node->val);

if (node->left) enqueue(queue, node->left);
if (node->right) enqueue(queue, node->right);
}
printf("\n"); // End of level
}

free(queue->data);
free(queue);
}

int main() {
printf("Build the binary tree:\n");
struct TreeNode* root = buildTree();

printf("\nLevel Order Traversal:\n");
levelOrder(root);

return 0;
}
100 changes: 100 additions & 0 deletions Deadlock avoidance algorithm/Banker's Algorithm.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
#include <stdio.h>
#include <stdbool.h>

#define MAX_PROCESSES 10
#define MAX_RESOURCES 10

// Function to check if the system is in a safe state
bool isSafe(int processes, int resources, int max[MAX_PROCESSES][MAX_RESOURCES],
int allocation[MAX_PROCESSES][MAX_RESOURCES], int available[MAX_RESOURCES]) {

int work[MAX_RESOURCES];
bool finish[MAX_PROCESSES] = {false};
int safeSequence[MAX_PROCESSES];
int count = 0;

// Initialize work to available resources
for (int i = 0; i < resources; i++) {
work[i] = available[i];
}

// Find a safe sequence
while (count < processes) {
bool found = false;
for (int p = 0; p < processes; p++) {
if (!finish[p]) {
bool canAllocate = true;
for (int r = 0; r < resources; r++) {
if (max[p][r] - allocation[p][r] > work[r]) {
canAllocate = false;
break;
}
}

// If a process can be allocated
if (canAllocate) {
for (int r = 0; r < resources; r++) {
work[r] += allocation[p][r];
}
safeSequence[count++] = p;
finish[p] = true;
found = true;
}
}
}

// If no process can be allocated, then system is not in a safe state
if (!found) {
printf("System is not in a safe state.\n");
return false;
}
}

// Print safe sequence
printf("System is in a safe state.\nSafe sequence: ");
for (int i = 0; i < processes; i++) {
printf("%d ", safeSequence[i]);
}
printf("\n");
return true;
}

int main() {
int processes, resources;
int max[MAX_PROCESSES][MAX_RESOURCES];
int allocation[MAX_PROCESSES][MAX_RESOURCES];
int available[MAX_RESOURCES];

// Input the number of processes and resources
printf("Enter number of processes: ");
scanf("%d", &processes);
printf("Enter number of resources: ");
scanf("%d", &resources);

// Input the Max matrix
printf("Enter the Max matrix:\n");
for (int i = 0; i < processes; i++) {
for (int j = 0; j < resources; j++) {
scanf("%d", &max[i][j]);
}
}

// Input the Allocation matrix
printf("Enter the Allocation matrix:\n");
for (int i = 0; i < processes; i++) {
for (int j = 0; j < resources; j++) {
scanf("%d", &allocation[i][j]);
}
}

// Input the Available resources
printf("Enter the Available resources:\n");
for (int i = 0; i < resources; i++) {
scanf("%d", &available[i]);
}

// Check if the system is in a safe state
isSafe(processes, resources, max, allocation, available);

return 0;
}
64 changes: 64 additions & 0 deletions Deadlock avoidance algorithm/Readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# Banker's Algorithm in C

This project implements the **Banker's Algorithm** in C, a classic deadlock avoidance algorithm used in operating systems. The algorithm checks if resource allocation requests can be safely granted without causing deadlock by ensuring that the system remains in a "safe state" after each allocation.

## Table of Contents
- [Introduction](#introduction)
- [Algorithm Overview](#algorithm-overview)
- [Features](#features)
- [Example](#example)
- [Limitations](#limitations)

## Introduction

The Banker's Algorithm, designed by Edsger Dijkstra, is a deadlock avoidance algorithm that allocates resources to processes only if the system can remain in a safe state. A "safe state" is one where a sequence of processes can complete without running into resource contention issues that would lead to deadlock.

## Algorithm Overview

The Banker's Algorithm operates based on three main matrices:
- **Max Matrix**: Indicates the maximum resources each process may require.
- **Allocation Matrix**: Shows the resources currently allocated to each process.
- **Available Vector**: Tracks the currently available resources in the system.

When a process requests resources, the algorithm calculates if fulfilling the request will keep the system in a safe state. If so, the resources are allocated; otherwise, the request is denied.

## Features

- Deadlock avoidance for resource allocation.
- Identification of a safe sequence for process execution.
- Simple implementation using arrays and loops, compatible with standard C libraries.

## Example

### Example 1

#### Sample Input

Enter number of processes: 3
Enter number of resources: 3

Enter the Max matrix:
7 5 3
3 2 2
9 0 2

Enter the Allocation matrix:
0 1 0
2 0 0
3 0 2

Enter the Available resources:
3 3 2

#### Sample Input

System is in a safe state.
Safe sequence: 1 0 2

## Limitations

- **Fixed Resource and Process Count**: This implementation sets maximum limits for the number of processes and resources. Modifying these limits requires changing the code and recompiling.
- **Static Resource Allocation**: The algorithm only supports a static allocation based on the initial request. Dynamic resource changes or multiple resource requests are not handled.
- **Non-Preemptive**: Once allocated, resources cannot be preempted or re-assigned from one process to another, limiting flexibility.
- **Single Resource Type Per Process**: The current implementation assumes that each process only requests one type of resource at a time. For complex requests, code adjustments are needed.
- **Sequential Execution**: The algorithm performs sequential checks to find a safe sequence, which can be inefficient for systems with a large number of processes and resources.
Loading

0 comments on commit fd0b856

Please sign in to comment.