Skip to content

Commit

Permalink
Merge pull request #73 from nishakp3005/graph_algos
Browse files Browse the repository at this point in the history
added algorithms related to graphs
  • Loading branch information
ajay-dhangar authored Oct 5, 2024
2 parents cb55fa6 + fa96000 commit 39b2beb
Show file tree
Hide file tree
Showing 10 changed files with 1,321 additions and 0 deletions.
156 changes: 156 additions & 0 deletions docs/graphs/Graph connectivity Algorithms/Kosaraju's Algorithm.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
---
id: kosarajus-algorithm
title: Kosaraju's Algorithm
sidebar_label: Kosaraju's Algorithm
description: "In this blog post, we'll delve into Kosaraju's Algorithm, a classic method for finding strongly connected components (SCCs) in a directed graph. We'll cover its implementation, time complexity, and use cases in various applications such as circuit design and social network analysis."
tags: [dsa, algorithms, graph connectivity]
---

# Kosaraju’s Algorithm

## Introduction

Kosaraju’s Algorithm is another efficient method for finding strongly connected components (SCCs) in a directed graph. It utilizes two passes of depth-first search (DFS): one on the original graph and another on the transposed graph. This algorithm effectively identifies all SCCs in linear time.

## Implementation

The implementation of Kosaraju's Algorithm involves the following steps:

1. **First Pass**:
- Perform DFS on the original graph to determine the finishing order of vertices.
- Push each finished vertex onto a stack.

2. **Transpose Graph**:
- Reverse all edges in the graph to create a transposed graph.

3. **Second Pass**:
- Pop vertices from the stack and perform DFS on the transposed graph.
- Each DFS call identifies one strongly connected component.

## Code in Java

Here’s a sample implementation of Kosaraju’s Algorithm in Java:

```java
import java.util.*;

public class KosarajusAlgorithm {
private List<List<Integer>> adj;
private List<List<Integer>> transposedAdj;

public KosarajusAlgorithm(int vertices) {
adj = new ArrayList<>(vertices);
transposedAdj = new ArrayList<>(vertices);

for (int i = 0; i < vertices; i++) {
adj.add(new ArrayList<>());
transposedAdj.add(new ArrayList<>());
}
}

public void addEdge(int u, int v) {
adj.get(u).add(v);
}

private void dfs(int v, boolean[] visited, Stack<Integer> stack) {
visited[v] = true;

for (int neighbor : adj.get(v)) {
if (!visited[neighbor]) {
dfs(neighbor, visited, stack);
}
}

stack.push(v); // Push finished vertex onto stack
}

private void transposeGraph() {
for (int u = 0; u < adj.size(); u++) {
for (int v : adj.get(u)) {
transposedAdj.get(v).add(u); // Reverse edge
}
}
}

public List<List<Integer>> findSCCs() {
Stack<Integer> stack = new Stack<>();

boolean[] visited = new boolean[adj.size()];

// First pass: fill stack with finishing order
for (int i = 0; i < adj.size(); i++) {
if (!visited[i]) {
dfs(i, visited, stack);
}
}

transposeGraph(); // Create transposed graph

Arrays.fill(visited, false); // Reset visited array

List<List<Integer>> sccs = new ArrayList<>();

// Second pass: process all vertices in order defined by stack
while (!stack.isEmpty()) {
int v = stack.pop();

if (!visited[v]) {
List<Integer> scc = new ArrayList<>();
dfsUtil(v, visited, scc); // Perform DFS on transposed graph
sccs.add(scc); // Add found SCC to result list
}
}

return sccs;
}

private void dfsUtil(int v, boolean[] visited, List<Integer> scc) {
visited[v] = true;
scc.add(v);

for (int neighbor : transposedAdj.get(v)) {
if (!visited[neighbor]) {
dfsUtil(neighbor, visited, scc);
}
}
}

public static void main(String[] args) {
KosarajusAlgorithm graph = new KosarajusAlgorithm(5);

// Example graph edges
graph.addEdge(0, 2);
graph.addEdge(2, 1);
graph.addEdge(1, 0);
graph.addEdge(0, 3);
graph.addEdge(3, 4);

List<List<Integer>> sccs = graph.findSCCs();

System.out.println("Strongly Connected Components:");
for (List<Integer> scc : sccs) {
System.out.println(scc);
}
}
}
```

## Time Complexity and Space Complexity

### Time Complexity

The time complexity of Kosaraju’s Algorithm is \( O(V + E) \), where \( V \) is the number of vertices and \( E \) is the number of edges. This efficiency arises from performing two passes through all vertices and edges.

### Space Complexity

The space complexity is \( O(V + E) \), which accounts for:
- The storage of both the adjacency list and transposed adjacency list.
- The stack used during DFS.

## Points to Remember

1. **Strongly Connected Components**: Kosaraju's Algorithm efficiently identifies all SCCs in a directed graph.
2. **Two Passes**: The algorithm requires two passes through the graph—one on the original and one on the transposed version.
3. **Graph Type**: This algorithm works only on directed graphs.
4. **Applications**: Useful in various applications such as circuit design and analyzing social networks.
5. **Efficiency**: Like Tarjan's Algorithm, it operates in linear time relative to the size of the input.
136 changes: 136 additions & 0 deletions docs/graphs/Graph connectivity Algorithms/Tarjan’s Algorithm.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
---
id: tarjans-algorithm
title: Tarjan's Algorithm
sidebar_label: Tarjan's Algorithm
description: "In this blog post, we'll explore Tarjan's Algorithm, an efficient method for finding strongly connected components (SCCs) in a directed graph. We'll discuss its implementation, time complexity, and practical applications in graph theory."
tags: [dsa, algorithms, graph connectivity]
---

# Tarjan’s Algorithm

## Introduction

Tarjan’s Algorithm is an efficient method for finding strongly connected components (SCCs) in a directed graph. A strongly connected component is a maximal subgraph where every vertex is reachable from every other vertex within that component. The algorithm uses depth-first search (DFS) and maintains a low-link value to identify SCCs in linear time.

## Implementation

The implementation of Tarjan's Algorithm involves the following steps:

1. **Initialize**:
- Create arrays to store discovery times and low-link values for each vertex.
- Use a stack to keep track of the vertices in the current path of DFS.
- Maintain a boolean array to track which vertices are in the stack.

2. **Perform DFS**:
- For each unvisited vertex, perform a DFS.
- Update discovery times and low-link values.
- If the current vertex is the root of an SCC, pop vertices from the stack until the root is reached.

## Code in Java

Here’s a sample implementation of Tarjan’s Algorithm in Java:

```java
import java.util.*;

public class TarjansAlgorithm {
private int time = 0;
private List<List<Integer>> adj;
private Stack<Integer> stack;
private boolean[] onStack;
private int[] disc;
private int[] low;
private List<List<Integer>> sccs;

public TarjansAlgorithm(int vertices) {
adj = new ArrayList<>(vertices);
for (int i = 0; i < vertices; i++) {
adj.add(new ArrayList<>());
}
stack = new Stack<>();
onStack = new boolean[vertices];
disc = new int[vertices];
low = new int[vertices];
Arrays.fill(disc, -1);
Arrays.fill(low, -1);
sccs = new ArrayList<>();
}

public void addEdge(int u, int v) {
adj.get(u).add(v);
}

public void tarjanDFS(int u) {
disc[u] = low[u] = time++;
stack.push(u);
onStack[u] = true;

for (int v : adj.get(u)) {
if (disc[v] == -1) {
tarjanDFS(v);
low[u] = Math.min(low[u], low[v]);
} else if (onStack[v]) {
low[u] = Math.min(low[u], disc[v]);
}
}

if (low[u] == disc[u]) {
List<Integer> scc = new ArrayList<>();
int w;
do {
w = stack.pop();
onStack[w] = false;
scc.add(w);
} while (w != u);
sccs.add(scc);
}
}

public List<List<Integer>> findSCCs() {
for (int i = 0; i < adj.size(); i++) {
if (disc[i] == -1) {
tarjanDFS(i);
}
}
return sccs;
}

public static void main(String[] args) {
TarjansAlgorithm graph = new TarjansAlgorithm(5);

// Example graph edges
graph.addEdge(0, 2);
graph.addEdge(2, 1);
graph.addEdge(1, 0);
graph.addEdge(0, 3);
graph.addEdge(3, 4);

List<List<Integer>> sccs = graph.findSCCs();

System.out.println("Strongly Connected Components:");
for (List<Integer> scc : sccs) {
System.out.println(scc);
}
}
}
```

## Time Complexity and Space Complexity

### Time Complexity

The time complexity of Tarjan’s Algorithm is \( O(V + E) \), where \( V \) is the number of vertices and \( E \) is the number of edges. This efficiency arises from the single pass through all vertices and edges during the DFS.

### Space Complexity

The space complexity is \( O(V) \), which accounts for:
- The storage of the adjacency list.
- The stack used for maintaining vertices during DFS.

## Points to Remember

1. **Strongly Connected Components**: Tarjan's Algorithm identifies all SCCs in a directed graph efficiently.
2. **Single Pass**: The algorithm processes each vertex and edge only once.
3. **Low-Link Values**: The use of low-link values helps in determining the root of SCCs.
4. **Graph Type**: This algorithm works only on directed graphs.
5. **Applications**: Useful in various applications such as circuit design and analyzing social networks.
Loading

0 comments on commit 39b2beb

Please sign in to comment.