Skip to content

Commit

Permalink
Merge pull request #256 from Mayur-nimkande-20/mayur
Browse files Browse the repository at this point in the history
Add graphs basics folder
  • Loading branch information
AkhzarFarhan authored Oct 24, 2024
2 parents d216043 + 60198d2 commit a4c7dc8
Show file tree
Hide file tree
Showing 10 changed files with 601 additions and 0 deletions.
129 changes: 129 additions & 0 deletions C++/Graphs_Basix/CHEAT_SHEET.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@

# Graph Data Structure Cheat Sheet

## 1. What is a Graph?
A **Graph** is a data structure consisting of a set of nodes (or vertices) and edges that connect these nodes.

- **Vertices (V)**: Individual entities in the graph.
- **Edges (E)**: Connections between two vertices.

A graph is represented as **G(V, E)**, where:
- **V** is a set of vertices
- **E** is a set of edges

### Types of Graphs:
1. **Directed Graph (Digraph)**: Edges have direction (u → v).
2. **Undirected Graph**: Edges are bidirectional (u ↔ v).
3. **Weighted Graph**: Edges have weights or costs associated with them.
4. **Unweighted Graph**: All edges have the same weight or no weight at all.

### Common Terminologies:
- **Adjacency**: Two vertices are adjacent if they are connected by an edge.
- **Degree**: The number of edges connected to a vertex.
- **Path**: A sequence of vertices where each adjacent pair is connected by an edge.
- **Cycle**: A path where the first and last vertices are the same.

## 2. Graph Representation

### 2.1 Adjacency Matrix
An `N x N` matrix is used to represent the graph where `N` is the number of vertices.
- **adj[i][j] = 1** if there is an edge from vertex `i` to vertex `j`.
- **adj[i][j] = 0** otherwise.

### 2.2 Adjacency List
Each vertex has a list of all vertices it is connected to. This representation is more space-efficient for sparse graphs.

## 3. Graph Traversal

### 3.1 Breadth-First Search (BFS)
A level-order traversal technique that starts from a given node and visits all its neighbors, then proceeds to the neighbors' neighbors.

### 3.2 Depth-First Search (DFS)
DFS explores as far as possible along each branch before backtracking.

## 4. Common Graph Algorithms

### 4.1 Shortest Path Algorithms
- **Dijkstra’s Algorithm**: Finds the shortest path from a single source to all other vertices (for non-negative weights).
- **Bellman-Ford Algorithm**: Handles graphs with negative weights.
- **Floyd-Warshall Algorithm**: Finds the shortest paths between all pairs of vertices.

### 4.2 Minimum Spanning Tree Algorithms
- **Prim’s Algorithm**: Greedy algorithm to find the MST, starting from any node.
- **Kruskal’s Algorithm**: Uses union-find to select the shortest edges.

### 4.3 Topological Sorting
A linear ordering of vertices in a directed acyclic graph (DAG).

### 4.4 Detecting Cycles
- Use DFS to detect cycles in directed/undirected graphs.

### 4.5 Strongly Connected Components (Kosaraju’s Algorithm)
Decomposes a directed graph into strongly connected components.

## 5. Frequently Asked Graph Problems

### 5.1 Basic Graph Traversal
- BFS of a graph
- DFS of a graph
- Connected Components

### 5.2 Shortest Paths
- Dijkstra’s Algorithm
- Bellman-Ford Algorithm
- Shortest Path in Binary Maze

### 5.3 MST (Minimum Spanning Tree)
- Prim's MST
- Kruskal's MST

### 5.4 Advanced Graph Problems
- Topological Sort of a Directed Graph
- Detect Cycle in Directed Graph
- Strongly Connected Components

## 6. Frequently Asked DSA Graph Questions

1. **Breadth-First Search (BFS) and Depth-First Search (DFS)**
- Implement BFS and DFS for a graph.
- Find the number of connected components in an undirected graph.

2. **Shortest Path Algorithms**
- Find the shortest path in an unweighted graph (BFS).
- Find the shortest path in a weighted graph (Dijkstra, Bellman-Ford).

3. **Cycle Detection**
- Detect a cycle in an undirected graph (DFS).
- Detect a cycle in a directed graph (DFS with backtracking).

4. **Topological Sort**
- Find the topological order of vertices in a directed acyclic graph (Kahn's Algorithm or DFS-based approach).

5. **Minimum Spanning Tree (MST)**
- Implement Prim’s algorithm.
- Implement Kruskal’s algorithm.

6. **Strongly Connected Components**
- Find all the strongly connected components (SCCs) in a directed graph (Kosaraju’s algorithm, Tarjan’s algorithm).

7. **Graph Coloring**
- Implement graph coloring using BFS/DFS.
- Check if a graph is bipartite.

8. **Miscellaneous**
- Find the number of islands in a matrix (connected components problem).
- Clone a graph (deep copy of a graph).

## 7. Common Interview Questions
1. **Leetcode 200:** Number of Islands
2. **Leetcode 207:** Course Schedule (Topological Sort)
3. **Leetcode 743:** Network Delay Time (Dijkstra)
4. **Leetcode 785:** Is Graph Bipartite?
5. **Leetcode 997:** Find the Town Judge
6. **Leetcode 399:** Evaluate Division (Graph Representation of Equations)

--

## Credits

This cheat sheet was created by [Mayur Nimkande](https://github.com/Mayur-nimkande-20), whose contributions are greatly appreciated.
53 changes: 53 additions & 0 deletions C++/Graphs_Basix/codes/bellman_ford.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// ## Credits

// This cheat sheet was created by [Mayur Nimkande](https://github.com/Mayur-nimkande-20), whose contributions are greatly appreciated.


#include <iostream>
#include <vector>

using namespace std;

const int INF = 1e9; // A large value representing infinity

// Function to implement Bellman-Ford algorithm for finding the shortest path
bool bellmanFord(int start, int V, vector<vector<int>>& edges, vector<int>& dist) {
dist[start] = 0; // Distance to the start node is 0

// Relax edges repeatedly
for (int i = 0; i < V - 1; i++) {
for (auto edge : edges) {
int u = edge[0]; // Starting node of the edge
int v = edge[1]; // Ending node of the edge
int weight = edge[2]; // Weight of the edge

// If the current distance to u is not infinite
if (dist[u] != INF && dist[u] + weight < dist[v]) {
dist[v] = dist[u] + weight; // Update the distance to v
}
}
}

// Check for negative-weight cycles
for (auto edge : edges) {
int u = edge[0];
int v = edge[1];
int weight = edge[2];

// If we can still relax the edge, there is a negative cycle
if (dist[u] != INF && dist[u] + weight < dist[v]) {
return false; // Negative cycle found
}
}

return true; // No negative cycles found
}

/*
Explanation:
- This function implements the Bellman-Ford algorithm to find the shortest paths from a starting node to all other nodes in a graph.
- Unlike Dijkstra's, it can handle negative weights and detects negative cycles.
- The algorithm relaxes all edges multiple times (V-1 times, where V is the number of vertices).
- After relaxation, it checks for negative cycles by attempting to relax the edges one more time.
- It returns a boolean indicating whether a negative cycle was detected.
*/
45 changes: 45 additions & 0 deletions C++/Graphs_Basix/codes/bfs.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// ## Credits

// This cheat sheet was created by [Mayur Nimkande](https://github.com/Mayur-nimkande-20), whose contributions are greatly appreciated.


#include <iostream>
#include <vector>
#include <queue>

using namespace std;

// Function to perform Breadth-First Search (BFS)
void bfs(int start, vector<vector<int>>& adj) {
// Create a queue to hold nodes to visit
queue<int> q;
// Create a visited array to keep track of visited nodes
vector<bool> visited(adj.size(), false);

// Start the BFS from the 'start' node
q.push(start);
visited[start] = true; // Mark the start node as visited

while (!q.empty()) { // While there are nodes to visit
int node = q.front(); // Get the front node of the queue
cout << node << " "; // Print the node (or process it)
q.pop(); // Remove the node from the queue

// Visit all the neighbors of the current node
for (int neighbor : adj[node]) {
if (!visited[neighbor]) { // If the neighbor hasn't been visited
q.push(neighbor); // Add it to the queue for visiting
visited[neighbor] = true; // Mark it as visited
}
}
}
}

/*
Explanation:
- This function implements Breadth-First Search (BFS) on a graph.
- It starts from a specified node (the 'start' node) and explores all of its neighboring nodes first.
- It uses a queue to keep track of nodes that need to be visited, ensuring that nodes are processed in the order they are discovered.
- A 'visited' array is used to mark nodes as visited to prevent re-visiting them, which would lead to an infinite loop.
- The function prints out each node as it is visited.
*/
37 changes: 37 additions & 0 deletions C++/Graphs_Basix/codes/dfs.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// ## Credits

// This cheat sheet was created by [Mayur Nimkande](https://github.com/Mayur-nimkande-20), whose contributions are greatly appreciated.


#include <iostream>
#include <vector>

using namespace std;

// Utility function for DFS
void dfsUtil(int node, vector<vector<int>>& adj, vector<bool>& visited) {
visited[node] = true; // Mark the current node as visited
cout << node << " "; // Print the node (or process it)

// Visit all the neighbors of the current node
for (int neighbor : adj[node]) {
if (!visited[neighbor]) { // If the neighbor hasn't been visited
dfsUtil(neighbor, adj, visited); // Recursively visit it
}
}
}

// Function to perform Depth-First Search (DFS)
void dfs(int start, vector<vector<int>>& adj) {
vector<bool> visited(adj.size(), false); // Keep track of visited nodes
dfsUtil(start, adj, visited); // Start DFS from the 'start' node
}

/*
Explanation:
- This function performs Depth-First Search (DFS) on a graph.
- DFS explores as far as possible along each branch before backtracking, creating a path-like exploration.
- The 'dfsUtil' function is a utility that performs the actual recursion for exploring nodes.
- Similar to BFS, a 'visited' array is used to keep track of which nodes have been visited, preventing cycles.
- The function prints each node as it is visited.
*/
51 changes: 51 additions & 0 deletions C++/Graphs_Basix/codes/dijkstra.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// ## Credits

// This cheat sheet was created by [Mayur Nimkande](https://github.com/Mayur-nimkande-20), whose contributions are greatly appreciated.


#include <iostream>
#include <vector>
#include <queue>

using namespace std;

const int INF = 1e9; // A large value representing infinity

// Function to implement Dijkstra's algorithm for finding the shortest path
vector<int> dijkstra(int start, vector<vector<pair<int, int>>>& graph) {
int V = graph.size(); // Number of vertices
vector<int> dist(V, INF); // Distance array, initialized to "infinity"
dist[start] = 0; // Distance to the starting node is 0

// Min-heap (priority queue) to hold nodes and their distances
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;
pq.push({0, start}); // Start from the initial node

while (!pq.empty()) { // While there are nodes to process
int u = pq.top().second; // Get the node with the smallest distance
pq.pop(); // Remove it from the queue

// Explore neighbors of the current node
for (auto& edge : graph[u]) {
int v = edge.first; // The neighboring node
int weight = edge.second; // The distance to the neighbor

// If a shorter path to neighbor is found
if (dist[u] + weight < dist[v]) {
dist[v] = dist[u] + weight; // Update distance
pq.push({dist[v], v}); // Add neighbor to the queue
}
}
}

return dist; // Return the distances from the start node
}

/*
Explanation:
- This function implements Dijkstra's algorithm to find the shortest path from a starting node to all other nodes in a weighted graph.
- It uses a priority queue (min-heap) to process the next node with the smallest known distance.
- The 'dist' array keeps track of the shortest distance from the start node to every other node.
- The algorithm iteratively updates the distances to each neighboring node based on the current node's distance.
- It returns an array of the shortest distances to all nodes from the start node.
*/
Loading

0 comments on commit a4c7dc8

Please sign in to comment.