Total Pageviews

Tuesday, September 15, 2026

C++ • SELF-BALANCING BST Red-Black Tree (Insertion, Deletion, Display)

C++ • SELF-BALANCING BST

Red-Black Tree (Insertion, Deletion, Display)

DATA STRUCTURE
Red-Black Tree
SEARCH / INS / DEL
O(log n)
SPACE COMPLEXITY
O(n)
TYPE
Self-Balancing BST

C++ Implementation

red_black_tree.cpp
#include <iostream>
using namespace std;

enum Color { RED, BLACK };

struct Node {
    int data;
    Color color;
    Node *left, *right, *parent;

    Node(int val) : data(val), color(RED), left(nullptr), right(nullptr), parent(nullptr) {}
};

class RedBlackTree {
    Node* root;
    Node* TNULL;

    // Initialize NULL leaf node in constructor
    void initializeNULLNode(Node* node, Node* parent) {
        node->data = 0;
        node->color = BLACK;
        node->left = nullptr;
        node->right = nullptr;
        node->parent = parent;
    }

    void preOrderHelper(Node* node) {
        if (node != TNULL) {
            cout << node->data << "(" << (node->color == RED ? "R" : "B") << ") ";
            preOrderHelper(node->left);
            preOrderHelper(node->right);
        }
    }

    void inOrderHelper(Node* node) {
        if (node != TNULL) {
            inOrderHelper(node->left);
            cout << node->data << "(" << (node->color == RED ? "R" : "B") << ") ";
            inOrderHelper(node->right);
        }
    }

    void postOrderHelper(Node* node) {
        if (node != TNULL) {
            postOrderHelper(node->left);
            postOrderHelper(node->right);
            cout << node->data << "(" << (node->color == RED ? "R" : "B") << ") ";
        }
    }

    Node* searchTreeHelper(Node* node, int key) {
        if (node == TNULL || key == node->data) {
            return node;
        }
        if (key < node->data) {
            return searchTreeHelper(node->left, key);
        }
        return searchTreeHelper(node->right, key);
    }

    void fixDelete(Node* x) {
        Node* s;
        while (x != root && x->color == BLACK) {
            if (x == x->parent->left) {
                s = x->parent->right;
                if (s->color == RED) {
                    s->color = BLACK;
                    x->parent->color = RED;
                    leftRotate(x->parent);
                    s = x->parent->right;
                }
                if (s->left->color == BLACK && s->right->color == BLACK) {
                    s->color = RED;
                    x = x->parent;
                } else {
                    if (s->right->color == BLACK) {
                        s->left->color = BLACK;
                        s->color = RED;
                        rightRotate(s);
                        s = x->parent->right;
                    }
                    s->color = x->parent->color;
                    x->parent->color = BLACK;
                    s->right->color = BLACK;
                    leftRotate(x->parent);
                    x = root;
                }
            } else {
                s = x->parent->left;
                if (s->color == RED) {
                    s->color = BLACK;
                    x->parent->color = RED;
                    rightRotate(x->parent);
                    s = x->parent->left;
                }
                if (s->right->color == BLACK && s->left->color == BLACK) {
                    s->color = RED;
                    x = x->parent;
                } else {
                    if (s->left->color == BLACK) {
                        s->right->color = BLACK;
                        s->color = RED;
                        leftRotate(s);
                        s = x->parent->left;
                    }
                    s->color = x->parent->color;
                    x->parent->color = BLACK;
                    s->left->color = BLACK;
                    rightRotate(x->parent);
                    x = root;
                }
            }
        }
        x->color = BLACK;
    }

    void rbTransplant(Node* u, Node* v) {
        if (u->parent == nullptr) {
            root = v;
        } else if (u == u->parent->left) {
            u->parent->left = v;
        } else {
            u->parent->right = v;
        }
        v->parent = u->parent;
    }

    void deleteNodeHelper(Node* node, int key) {
        Node* z = TNULL;
        Node* x, *y;
        while (node != TNULL) {
            if (node->data == key) {
                z = node;
            }
            if (node->data <= key) {
                node = node->right;
            } else {
                node = node->left;
            }
        }

        if (z == TNULL) {
            cout << "Key not found in the tree" << endl;
            return;
        }

        y = z;
        Color y_original_color = y->color;
        if (z->left == TNULL) {
            x = z->right;
            rbTransplant(z, z->right);
        } else if (z->right == TNULL) {
            x = z->left;
            rbTransplant(z, z->left);
        } else {
            y = minimum(z->right);
            y_original_color = y->color;
            x = y->right;
            if (y->parent == z) {
                x->parent = y;
            } else {
                rbTransplant(y, y->right);
                y->right = z->right;
                y->right->parent = y;
            }
            rbTransplant(z, y);
            y->left = z->left;
            y->left->parent = y;
            y->color = z->color;
        }
        delete z;
        if (y_original_color == BLACK) {
            fixDelete(x);
        }
    }

    void fixInsert(Node* k) {
        Node* u;
        while (k->parent->color == RED) {
            if (k->parent == k->parent->parent->left) {
                u = k->parent->parent->right;
                if (u->color == RED) {
                    u->color = BLACK;
                    k->parent->color = BLACK;
                    k->parent->parent->color = RED;
                    k = k->parent->parent;
                } else {
                    if (k == k->parent->right) {
                        k = k->parent;
                        leftRotate(k);
                    }
                    k->parent->color = BLACK;
                    k->parent->parent->color = RED;
                    rightRotate(k->parent->parent);
                }
            } else {
                u = k->parent->parent->left;
                if (u->color == RED) {
                    u->color = BLACK;
                    k->parent->color = BLACK;
                    k->parent->parent->color = RED;
                    k = k->parent->parent;
                } else {
                    if (k == k->parent->left) {
                        k = k->parent;
                        rightRotate(k);
                    }
                    k->parent->color = BLACK;
                    k->parent->parent->color = RED;
                    leftRotate(k->parent->parent);
                }
            }
            if (k == root) {
                break;
            }
        }
        root->color = BLACK;
    }

public:
    // Constructor
    RedBlackTree() {
        TNULL = new Node(0);
        TNULL->color = BLACK;
        TNULL->left = nullptr;
        TNULL->right = nullptr;
        root = TNULL;
    }

    void preorder() {
        preOrderHelper(this->root);
    }

    void inorder() {
        inOrderHelper(this->root);
    }

    void postorder() {
        postOrderHelper(this->root);
    }

    Node* searchTree(int k) {
        return searchTreeHelper(this->root, k);
    }

    Node* minimum(Node* node) {
        while (node->left != TNULL) {
            node = node->left;
        }
        return node;
    }

    void leftRotate(Node* x) {
        Node* y = x->right;
        x->right = y->left;
        if (y->left != TNULL) {
            y->left->parent = x;
        }
        y->parent = x->parent;
        if (x->parent == nullptr) {
            this->root = y;
        } else if (x == x->parent->left) {
            x->parent->left = y;
        } else {
            x->parent->right = y;
        }
        y->left = x;
        x->parent = y;
    }

    void rightRotate(Node* x) {
        Node* y = x->left;
        x->left = y->right;
        if (y->right != TNULL) {
            y->right->parent = x;
        }
        y->parent = x->parent;
        if (x->parent == nullptr) {
            this->root = y;
        } else if (x == x->parent->right) {
            x->parent->right = y;
        } else {
            x->parent->left = y;
        }
        y->right = x;
        x->parent = y;
    }

    // Insert function
    void insert(int key) {
        Node* node = new Node(key);
        node->parent = nullptr;
        node->data = key;
        node->left = TNULL;
        node->right = TNULL;
        node->color = RED;

        Node* y = nullptr;
        Node* x = this->root;

        while (x != TNULL) {
            y = x;
            if (node->data < x->data) {
                x = x->left;
            } else {
                x = x->right;
            }
        }

        node->parent = y;
        if (y == nullptr) {
            root = node;
        } else if (node->data < y->data) {
            y->left = node;
        } else {
            y->right = node;
        }

        if (node->parent == nullptr) {
            node->color = BLACK;
            return;
        }

        if (node->parent->parent == nullptr) {
            return;
        }

        fixInsert(node);
    }

    // Delete function
    void deleteNode(int data) {
        deleteNodeHelper(this->root, data);
    }
};

int main() {
    RedBlackTree bst;

    bst.insert(55);
    bst.insert(40);
    bst.insert(65);
    bst.insert(60);
    bst.insert(75);
    bst.insert(57);

    cout << "InOrder Traversal: ";
    bst.inorder();
    cout << endl;

    bst.deleteNode(40);

    cout << "InOrder Traversal after deleting 40: ";
    bst.inorder();
    cout << endl;

    return 0;
}

Sample Actions

Insert: 55, 40, 65, 60, 75, 57
Delete: 40

Output

InOrder Traversal: 40(B) 55(B) 57(B) 60(R) 65(B) 75(B) 
InOrder Traversal after deleting 40: 55(B) 57(B) 60(R) 65(B) 75(B) 

Line-by-Line Explanation

Code
Meaning
enum Color { RED, BLACK };
Defines node colors required by Red-Black Tree balancing rules.
struct Node
Represents a single node in the tree with data, color, left, right, and parent pointers.
class RedBlackTree
Encapsulates the tree structure, sentinel TNULL nodes, and self-balancing methods.
RedBlackTree()
Constructor initializing the root and sentinel null leaf nodes with BLACK color.
leftRotate(Node* x) / rightRotate(...)
Rotates sub-trees around node x to maintain balance properties during insert/delete.
void insert(int key)
Standard BST insertion followed by calling fixInsert() to resolve red-black violations.
void fixInsert(Node* k)
Recolors and rotates nodes if double-RED violations occur up the parent chain.
void deleteNode(int data)
Removes a node from the tree and triggers fixDelete() if a black node was removed.
void fixDelete(Node* x)
Restores black-height balance after a node deletion.
void inorder()
Displays elements in sorted order along with their node colors (R or B).
return 0;
Signals successful program execution.
How a Red-Black Tree works: A Red-Black Tree is a self-balancing binary search tree where every node is colored either red or black. By enforcing rules—such as no two red nodes can be adjacent, and every path from root to leaf must have the same number of black nodes—it guarantees that operations like search, insertion, and deletion run in O(log n) time.

C++ • GREEDY ALGORITHM Kruskal's Algorithm (Minimum Spanning Tree)

C++ • GREEDY ALGORITHM

Kruskal's Algorithm (Minimum Spanning Tree)

ALGORITHM
Kruskal's MST
TIME COMPLEXITY
O(E log E)
SPACE COMPLEXITY
O(V + E)
STRATEGY
Greedy / DSU

C++ Implementation

kruskal_mst.cpp
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

// Structure to represent a weighted edge
struct Edge {
    int u, v, weight;
    bool operator<(const Edge& other) const {
        return weight < other.weight;
    }
};

class KruskalMST
{
    int V, E;
    vector<Edge> edges;
    vector<int> parent;
    vector<int> rank;

    // Find set of vertex i (with path compression)
    int find(int i) {
        if (parent[i] == i)
            return i;
        return parent[i] = find(parent[i]);
    }

    // Union of two sets of x and y (by rank)
    void unionSets(int x, int y) {
        int rootX = find(x);
        int rootY = find(y);

        if (rootX != rootY) {
            if (rank[rootX] < rank[rootY]) {
                parent[rootX] = rootY;
            } else if (rank[rootX] > rank[rootY]) {
                parent[rootY] = rootX;
            } else {
                parent[rootY] = rootX;
                rank[rootX]++;
            }
        }
    }

public:

    // Constructor
    KruskalMST() {
        V = 0;
        E = 0;
    }

    // Input function
    void input() {
        cout << "Enter number of vertices: ";
        cin >> V;
        cout << "Enter number of edges: ";
        cin >> E;

        edges.resize(E);
        cout << "Enter edges (u v weight):\n";
        for (int i = 0; i < E; i++) {
            cin >> edges[i].u >> edges[i].v >> edges[i].weight;
        }
    }

    // Function to construct and print MST using Kruskal's algorithm
    void kruskalMST() {
        vector<Edge> result;
        int totalWeight = 0;

        // Sort all edges in non-decreasing order of their weight
        sort(edges.begin(), edges.end());

        parent.resize(V);
        rank.resize(V, 0);

        for (int i = 0; i < V; i++)
            parent[i] = i;

        int e = 0; // An index variable, used for result[]
        int i = 0; // An index variable, used for sorted edges

        // Number of edges to be taken is equal to V-1
        while (e < V - 1 && i < E) {
            Edge next_edge = edges[i++];

            int x = find(next_edge.u);
            int y = find(next_edge.v);

            // If including this edge does't cause a cycle, include it
            // in result and increment the index of result for next edge
            if (x != y) {
                result.push_back(next_edge);
                totalWeight += next_edge.weight;
                unionSets(x, y);
                e++;
            }
        }

        // Print the constructed MST
        cout << "Edge \tWeight\n";
        for (const auto& edge : result) {
            cout << edge.u << " - " << edge.v << " \t" << edge.weight << "\n";
        }
        cout << "Total Weight of MST: " << totalWeight << endl;
    }
};

int main() {
    KruskalMST obj;

    obj.input();
    obj.kruskalMST();

    return 0;
}

Sample Input

Enter number of vertices: 4
Enter number of edges: 5
Enter edges (u v weight):
0 1 10
0 2 6
0 3 5
1 3 15
2 3 4

Output

Edge 	Weight
2 - 3 	4 
0 - 3 	5 
0 - 1 	10 
Total Weight of MST: 19

Line-by-Line Explanation

Code
Meaning
struct Edge { u, v, weight; }
Defines a structure to hold the source, destination, and weight of each edge.
bool operator<(const Edge& ...)
Overloads the less-than operator to sort edges in ascending order of weight.
class KruskalMST
Creates a class named KruskalMST to encapsulate the Disjoint Set Union (DSU) and MST logic.
int find(int i)
Finds the representative/root of the set containing vertex i with path compression.
void unionSets(int x, int y)
Merges two disjoint sets containing x and y using union by rank.
KruskalMST()
Class constructor that initializes vertex and edge counts to zero.
void input()
Reads the number of vertices, edges, and edge details from the user.
sort(edges.begin(), edges.end());
Sorts all graph edges in non-decreasing order of weight.
if (x != y) { unionSets(x, y); }
Checks if adding the edge forms a cycle; if not, includes it in the MST.
KruskalMST obj;
Instantiates the KruskalMST object and triggers the constructor.
return 0;
Signals successful program execution.
How Kruskal's Algorithm works: Kruskal's algorithm is a greedy algorithm that finds a Minimum Spanning Tree (MST). It sorts all the edges from lowest weight to highest, then iterates through them and adds an edge to the MST only if the edge doesn't form a cycle (checked using a Disjoint Set Union / Union-Find data structure) until there are V - 1 edges in the tree.

C++ • GREEDY ALGORITHM Prim's Algorithm (Minimum Spanning Tree)

C++ • GREEDY ALGORITHM

Prim's Algorithm (Minimum Spanning Tree)

ALGORITHM
Prim's MST
TIME COMPLEXITY
O(V²)
SPACE COMPLEXITY
O(V)
STRATEGY
Greedy

C++ Implementation

prims_mst.cpp
#include <iostream>
#include <vector>
#include <climits>
using namespace std;

class PrimMST
{
    int V;
    int graph[100][100];

    // Utility function to find the vertex with minimum key value
    int minKey(int key[], bool mstSet[])
    {
        int min = INT_MAX, min_index;

        for (int v = 0; v < V; v++)
            if (mstSet[v] == false && key[v] < min)
                min = key[v], min_index = v;

        return min_index;
    }

public:

    // Constructor
    PrimMST()
    {
        V = 0;
    }

    // Input function
    void input()
    {
        cout << "Enter number of vertices: ";
        cin >> V;

        cout << "Enter adjacency matrix (" << V << " x " << V << "):\n";
        for (int i = 0; i < V; i++)
        {
            for (int j = 0; j < V; j++)
            {
                cin >> graph[i][j];
            }
        }
    }

    // Function to construct and print MST using Prim's algorithm
    void primMST()
    {
        int parent[100]; // Array to store constructed MST
        int key[100];    // Key values used to pick minimum weight edge
        bool mstSet[100]; // To represent set of vertices included in MST

        // Initialize all keys as INFINITE and mstSet[] as false
        for (int i = 0; i < V; i++)
            key[i] = INT_MAX, mstSet[i] = false;

        // Always include first 1st vertex in MST.
        key[0] = 0;     // Make key 0 so that this vertex is picked as first vertex
        parent[0] = -1; // First node is always root of MST

        // The MST will have V vertices
        for (int count = 0; count < V - 1; count++)
        {
            // Pick the minimum key vertex from the set of vertices not yet included in MST
            int u = minKey(key, mstSet);

            // Add the picked vertex to the MST Set
            mstSet[u] = true;

            // Update key value and parent index of the adjacent vertices of the picked vertex
            for (int v = 0; v < V; v++)
            {
                // graph[u][v] is non zero only for adjacent vertices of u
                // mstSet[v] is false for vertices not yet included in MST
                // Update the key only if graph[u][v] is smaller than key[v]
                if (graph[u][v] && mstSet[v] == false && graph[u][v] < key[v])
                    parent[v] = u, key[v] = graph[u][v];
            }
        }

        // Print the constructed MST
        cout << "Edge \tWeight\n";
        int totalWeight = 0;
        for (int i = 1; i < V; i++)
        {
            cout << parent[i] << " - " << i << " \t" << graph[i][parent[i]] << " \n";
            totalWeight += graph[i][parent[i]];
        }
        cout << "Total Weight of MST: " << totalWeight << endl;
    }
};

int main()
{
    PrimMST obj;

    obj.input();
    obj.primMST();

    return 0;
}

Sample Input

Enter number of vertices: 5
Enter adjacency matrix (5 x 5):
0 2 0 6 0
2 0 3 8 5
0 3 0 0 7
6 8 0 0 9
0 5 7 9 0

Output

Edge 	Weight
0 - 1 	2 
1 - 2 	3 
0 - 3 	6 
1 - 4 	5 
Total Weight of MST: 16

Line-by-Line Explanation

Code
Meaning
#include <iostream>
Includes standard input/output stream functions.
#include <climits>
Includes INT_MAX to represent infinity for edge weights.
class PrimMST
Creates a class named PrimMST to encapsulate the graph and MST logic.
int graph[100][100];
Adjacency matrix representation storing edge weights (0 means no direct edge).
int minKey(...)
Finds the unvisited vertex with the smallest tentative key/weight value.
PrimMST()
Class constructor that initializes vertex count to zero.
void input()
Reads the number of vertices and the adjacency matrix from the user.
key[0] = 0; parent[0] = -1;
Starts the MST selection from vertex 0 as the root.
mstSet[u] = true;
Marks the selected minimum-weight vertex as included in the MST.
parent[v] = u, key[v] = ...
Relaxes/updates the neighbor weights if a smaller connection to the MST is found.
PrimMST obj;
Instantiates the PrimMST object and triggers the constructor.
return 0;
Signals successful program execution.
How Prim's Algorithm works: Prim's algorithm is a greedy approach to find a Minimum Spanning Tree (MST) for a weighted undirected graph. It starts with an arbitrary node, grows the spanning tree edge by edge by always picking the minimum-weight edge that connects a vertex in the MST to a vertex outside the MST, until all vertices are included.

C++ • GRAPH TRAVERSAL Depth-First Search (DFS)

C++ • GRAPH TRAVERSAL

Depth-First Search (DFS)

ALGORITHM
Depth-First Search
TIME COMPLEXITY
O(V + E)
SPACE COMPLEXITY
O(V)
STRUCTURE
Recursion / Stack

C++ Implementation

dfs_graph.cpp
#include <iostream>
#include <vector>
using namespace std;

class GraphDFS
{
    int V; // Number of vertices
    vector<vector<int>> adj; // Adjacency list
    vector<bool> visited;

    // Helper recursive function for DFS
    void dfsHelper(int curr)
    {
        visited[curr] = true;
        cout << curr << " ";

        for (int neighbor : adj[curr])
        {
            if (!visited[neighbor])
            {
                dfsHelper(neighbor);
            }
        }
    }

public:

    // Constructor
    GraphDFS()
    {
        V = 0;
    }

    // Input function to read graph structure
    void input()
    {
        int E;
        cout << "Enter number of vertices: ";
        cin >> V;
        adj.resize(V);

        cout << "Enter number of edges: ";
        cin >> E;

        cout << "Enter edges (u v for undirected edge):\n";
        for (int i = 0; i < E; i++)
        {
            int u, v;
            cin >> u >> v;
            adj[u].push_back(v);
            adj[v].push_back(u);
        }
    }

    // Depth-First Search interface function
    void dfs(int startNode)
    {
        visited.assign(V, false);
        cout << "DFS Traversal: ";
        dfsHelper(startNode);
        cout << endl;
    }
};

int main()
{
    GraphDFS obj;

    obj.input();
    
    int start;
    cout << "Enter starting vertex: ";
    cin >> start;

    obj.dfs(start);

    return 0;
}

Sample Input

Enter number of vertices: 5
Enter number of edges: 5
Enter edges (u v for undirected edge):
0 1
0 2
1 3
1 4
2 4
Enter starting vertex: 0

Output

DFS Traversal: 
0 1 3 4 2 

Line-by-Line Explanation

Code
Meaning
#include <iostream>
Includes standard input/output stream functions.
#include <vector>
Includes dynamic array support for adjacency list and visited tracking.
class GraphDFS
Creates a class named GraphDFS to encapsulate graph data and traversal methods.
vector<vector<int>> adj;
Adjacency list representation storing neighbors for each vertex.
void dfsHelper(int curr)
Recursive utility function that explores deep down each branch of the graph.
GraphDFS()
Class constructor that initializes vertex count to zero.
void input()
Reads the number of vertices, edges, and connections from the user.
visited.assign(V, false);
Resets and tracks which vertices have already been visited.
visited[curr] = true;
Marks the current node as visited before exploring its neighbors.
dfsHelper(neighbor);
Recursively calls DFS on an unvisited neighbor, diving deeper into the graph.
GraphDFS obj;
Instantiates the GraphDFS object and triggers the constructor.
return 0;
Signals successful program execution.
How Depth-First Search (DFS) works: DFS explores a graph by going as deep as possible along each branch before backtracking. Starting from a chosen vertex, it marks it as visited, prints/processes it, and recursively visits the first unvisited neighbor until it hits a dead end, at which point it backtracks to explore remaining paths.

C++ • GRAPH TRAVERSAL Breadth-First Search (BFS)

C++ • GRAPH TRAVERSAL

Breadth-First Search (BFS)

ALGORITHM
Breadth-First Search
TIME COMPLEXITY
O(V + E)
SPACE COMPLEXITY
O(V)
STRUCTURE
Queue

C++ Implementation

bfs_graph.cpp
#include <iostream>
#include <vector>
#include <queue>
using namespace std;

class GraphBFS
{
    int V; // Number of vertices
    vector<vector<int>> adj; // Adjacency list

public:

    // Constructor
    GraphBFS()
    {
        V = 0;
    }

    // Input function to read graph structure
    void input()
    {
        int E;
        cout << "Enter number of vertices: ";
        cin >> V;
        adj.resize(V);

        cout << "Enter number of edges: ";
        cin >> E;

        cout << "Enter edges (u v for undirected edge):\n";
        for (int i = 0; i < E; i++)
        {
            int u, v;
            cin >> u >> v;
            adj[u].push_back(v);
            adj[v].push_back(u);
        }
    }

    // Breadth-First Search function
    void bfs(int startNode)
    {
        vector<bool> visited(V, false);
        queue<int> q;

        visited[startNode] = true;
        q.push(startNode);

        cout << "BFS Traversal: ";

        while (!q.empty())
        {
            int curr = q.front();
            q.pop();
            cout << curr << " ";

            for (int neighbor : adj[curr])
            {
                if (!visited[neighbor])
                {
                    visited[neighbor] = true;
                    q.push(neighbor);
                }
            }
        }
        cout << endl;
    }
};

int main()
{
    GraphBFS obj;

    obj.input();
    
    int start;
    cout << "Enter starting vertex: ";
    cin >> start;

    obj.bfs(start);

    return 0;
}

Sample Input

Enter number of vertices: 5
Enter number of edges: 5
Enter edges (u v for undirected edge):
0 1
0 2
1 3
1 4
2 4
Enter starting vertex: 0

Output

BFS Traversal: 
0 1 2 3 4 

Line-by-Line Explanation

Code
Meaning
#include <iostream>
Includes standard input/output stream functions.
#include <vector>
Includes dynamic array support for adjacency list representation.
#include <queue>
Includes Queue data structure required for level-order traversal.
class GraphBFS
Creates a class named GraphBFS to encapsulate graph data and traversal methods.
vector<vector<int>> adj;
Adjacency list representation storing neighbors for each vertex.
GraphBFS()
Class constructor that initializes vertex count to zero.
void input()
Reads the number of vertices, edges, and connections from the user.
vector<bool> visited(V, false);
Tracks which vertices have already been visited to prevent infinite loops.
queue<int> q;
FIFO queue used to process vertices level by level.
q.push(startNode);
Enqueues the starting vertex and marks it as visited.
while (!q.empty())
Continues visiting nodes as long as there are elements remaining in the queue.
GraphBFS obj;
Instantiates the GraphBFS object and triggers the constructor.
return 0;
Signals successful program execution.
How Breadth-First Search (BFS) works: BFS explores a graph level by level starting from a chosen source vertex. It visits all immediate neighbors of the current vertex first, pushes them into a queue, and then processes those neighbors in the order they were discovered until all reachable nodes are visited.

C++ • DYNAMIC PROGRAMMING Longest Common Subsequence (LCS)

C++ • DYNAMIC PROGRAMMING

Longest Common Subsequence (LCS)

ALGORITHM
Longest Common Subsequence
TIME COMPLEXITY
O(m * n)
SPACE COMPLEXITY
O(m * n)
APPROACH
Dynamic Programming

C++ Implementation

longest_common_subsequence.cpp
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;

class SequenceLCS
{
    string s1, s2;
    int dp[105][105];

public:

    // Constructor
    SequenceLCS()
    {
        s1 = "";
        s2 = "";
    }

    // Input function
    void input()
    {
        cout << "Enter first sequence: ";
        cin >> s1;

        cout << "Enter second sequence: ";
        cin >> s2;
    }

    // Function to calculate LCS length and reconstruct the LCS string
    void findLCS()
    {
        int m = s1.length();
        int n = s2.length();

        // Building the DP table
        for (int i = 0; i <= m; i++)
        {
            for (int j = 0; j <= n; j++)
            {
                if (i == 0 || j == 0)
                    dp[i][j] = 0;
                else if (s1[i - 1] == s2[j - 1])
                    dp[i][j] = dp[i - 1][j - 1] + 1;
                else
                    dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
            }
        }

        // Reconstructing the LCS string from DP table
        int index = dp[m][n];
        string lcsStr = "";
        int i = m, j = n;

        while (i > 0 && j > 0)
        {
            if (s1[i - 1] == s2[j - 1])
            {
                lcsStr += s1[i - 1];
                i--;
                j--;
            }
            else if (dp[i - 1][j] > dp[i][j - 1])
            {
                i--;
            }
            else
            {
                j--;
            }
        }

        reverse(lcsStr.begin(), lcsStr.end());

        cout << "Length of LCS: " << dp[m][n] << endl;
        cout << "Longest Common Subsequence: " << lcsStr << endl;
    }
};

int main()
{
    SequenceLCS obj;

    obj.input();
    obj.findLCS();

    return 0;
}

Sample Input

Enter first sequence: AGGTAB
Enter second sequence: GXTXAYB

Output

Length of LCS: 4
Longest Common Subsequence: GTAB

Line-by-Line Explanation

Code
Meaning
#include <iostream>
Includes standard input/output stream functions.
#include <string>
Includes string handling support.
class SequenceLCS
Creates a class named SequenceLCS to encapsulate sequences and DP logic.
int dp[105][105];
2D array used to store lengths of longest common subsequences of sub-problems.
SequenceLCS()
Class constructor that initializes member strings to empty values.
void input()
Accepts the two input sequences/strings from the user.
if (s1[i - 1] == s2[j - 1])
If current characters match, add 1 to the result of the previous diagonal sub-problem.
dp[i][j] = max(...)
If characters don't match, take the maximum from the top or left cell.
while (i > 0 && j > 0)
Backtracks from the bottom-right corner of the DP table to reconstruct the actual LCS string.
reverse(lcsStr.begin(), ...)
Reverses the backtracked string since characters were gathered from end to start.
SequenceLCS obj;
Instantiates the SequenceLCS object and triggers the constructor.
return 0;
Signals successful program execution.
How Longest Common Subsequence works: LCS uses Dynamic Programming to build a 2D table where each cell dp[i][j] stores the length of the longest common subsequence of the prefixes s1[0..i-1] and s2[0..j-1]. By matching or skipping characters, it avoids redundant recursive calls and backtracks through the table to reconstruct the subsequence.

C++ • SORTING ALGORITHM Radix Sort

C++ • SORTING ALGORITHM

Radix Sort

ALGORITHM
Radix Sort
TIME COMPLEXITY
O(d * (n + b))
SPACE COMPLEXITY
O(n + b)
ORDER
Ascending

C++ Implementation

radix_sort.cpp
#include <iostream>
using namespace std;

class ArraySort
{
    int n;
    int a[100];

    // A utility function to get the maximum value in a[]
    int getMax()
    {
        int mx = a[0];
        for (int i = 1; i < n; i++)
            if (a[i] > mx)
                mx = a[i];
        return mx;
    }

    // A function to do counting sort of a[] according to the digit represented by exp
    void countSort(int exp)
    {
        int output[100]; // output array
        int i, count[10] = {0};

        // Store count of occurrences in count[]
        for (i = 0; i < n; i++)
            count[(a[i] / exp) % 10]++;

        // Change count[i] so that count[i] now contains actual
        // position of this digit in output[]
        for (i = 1; i < 10; i++)
            count[i] += count[i - 1];

        // Build the output array
        for (i = n - 1; i >= 0; i--)
        {
            output[count[(a[i] / exp) % 10] - 1] = a[i];
            count[(a[i] / exp) % 10]--;
        }

        // Copy the output array to a[], so that a[] now
        // contains sorted numbers according to current digit
        for (i = 0; i < n; i++)
            a[i] = output[i];
    }

public:

    // Constructor
    ArraySort()
    {
        n = 0;
    }

    // Input function
    void input()
    {
        cout << "Enter length of array: ";
        cin >> n;

        cout << "Enter array elements: ";

        for(int i = 0; i < n; i++)
        {
            cin >> a[i];
        }
    }

    // Radix Sort function
    void radixSort()
    {
        // Find the maximum number to know number of digits
        int m = getMax();

        // Do counting sort for every digit. Note that instead
        // of passing digit number, exp is 10^i where i is
        // the current digit position (1, 10, 100, ...)
        for (int exp = 1; m / exp > 0; exp *= 10)
            countSort(exp);
    }

    // Output function
    void output()
    {
        cout << "Sorted Array: ";

        for(int i = 0; i < n; i++)
        {
            cout << a[i] << " ";
        }
    }
};

int main()
{
    ArraySort obj;

    obj.input();
    obj.radixSort();
    obj.output();

    return 0;
}

Sample Input

Enter length of array: 5
Enter array elements:
170 45 75 90 802

Output

Sorted Array:
45 75 90 170 802

Line-by-Line Explanation

Code
Meaning
#include <iostream>
Includes standard input/output stream functions.
class ArraySort
Creates a class named ArraySort containing the array and sorting methods.
int n;
Stores the total number of elements in the array.
int a[100];
Declares an integer array capable of holding up to 100 elements.
int getMax()
Finds and returns the largest element in the array to determine the number of digits.
void countSort(int exp)
Sorts array elements based on the significant digit represented by exp (1's, 10's, 100's...).
ArraySort()
Class constructor that initializes object properties when instantiated.
n = 0;
Initializes the array size variable to zero.
void input()
Reads the array size and elements from the user.
for (int exp = 1; ...)
Loops through digit place values (1, 10, 100, ...) until all digits of the maximum number are processed.
void output()
Displays the final sorted array to the console.
ArraySort obj;
Instantiates the ArraySort object and triggers the constructor.
return 0;
Signals successful program execution.
How radix sort works: Radix sort is a non-comparative sorting algorithm. It sorts the numbers digit by digit, starting from the least significant digit (LSD) up to the most significant digit, using a stable sorting algorithm (Counting Sort) as a subroutine for each digit place.

C++ • SORTING ALGORITHM Non-Recursive Quick Sort

C++ • SORTING ALGORITHM

Non-Recursive Quick Sort

ALGORITHM
Iterative Quick Sort
TIME COMPLEXITY
O(n log n)
SPACE COMPLEXITY
O(n)
ORDER
Ascending

C++ Implementation

iterative_quick_sort.cpp
#include <iostream>
#include <stack>
using namespace std;

class ArraySort
{
    int n;
    int a[100];

    // Partition function to place pivot at correct position
    int partition(int low, int high)
    {
        int pivot = a[high];
        int i = (low - 1);

        for (int j = low; j <= high - 1; j++)
        {
            if (a[j] < pivot)
            {
                i++;
                swap(a[i], a[j]);
            }
        }
        swap(a[i + 1], a[high]);
        return (i + 1);
    }

public:

    // Constructor
    ArraySort()
    {
        n = 0;
    }

    // Input function
    void input()
    {
        cout << "Enter length of array: ";
        cin >> n;

        cout << "Enter array elements: ";

        for(int i = 0; i < n; i++)
        {
            cin >> a[i];
        }
    }

    // Non-Recursive (Iterative) Quick Sort function using an explicit stack
    void quickSort()
    {
        int stack[100];
        int top = -1;

        // Push initial values of low and high to stack
        stack[++top] = 0;
        stack[++top] = n - 1;

        // Pop from stack while it is not empty
        while (top >= 0)
        {
            int high = stack[top--];
            int low = stack[top--];

            // Set pivot element at its correct position in sorted array
            int pi = partition(low, high);

            // If there are elements on left side of pivot, then push left side to stack
            if (pi - 1 > low)
            {
                stack[++top] = low;
                stack[++top] = pi - 1;
            }

            // If there are elements on right side of pivot, then push right side to stack
            if (pi + 1 < high)
            {
                stack[++top] = pi + 1;
                stack[++top] = high;
            }
        }
    }

    // Output function
    void output()
    {
        cout << "Sorted Array: ";

        for(int i = 0; i < n; i++)
        {
            cout << a[i] << " ";
        }
    }
};

int main()
{
    ArraySort obj;

    obj.input();
    obj.quickSort();
    obj.output();

    return 0;
}

Sample Input

Enter length of array: 5
Enter array elements:
5 3 4 1 2

Output

Sorted Array:
1 2 3 4 5

Line-by-Line Explanation

Code
Meaning
#include <iostream>
Includes standard input/output stream functions.
class ArraySort
Creates a class named ArraySort containing the array and sorting methods.
int n;
Stores the total number of elements in the array.
int a[100];
Declares an integer array capable of holding up to 100 elements.
int partition(int low, int high)
Picks a pivot and rearranges the array so smaller elements go left and larger elements go right.
ArraySort()
Class constructor that initializes object properties when instantiated.
n = 0;
Initializes the array size variable to zero.
void input()
Reads the array size and elements from the user.
int stack[100]; top = -1;
Simulates the function call stack manually using an integer array.
stack[++top] = ...
Pushes the starting and ending indices (0 and n-1) onto the explicit stack.
while (top >= 0)
Loops as long as there are sub-arrays left to be processed in the stack.
void output()
Displays the final sorted array to the console.
ArraySort obj;
Instantiates the ArraySort object and triggers the constructor.
return 0;
Signals successful program execution.
How non-recursive quick sort works: Instead of using the compiler's function call stack (recursion), this approach uses an explicit auxiliary array/stack to store the lower and upper bounds of sub-arrays. It repeatedly pops a sub-range, partitions it around a pivot, and pushes the resulting left and right sub-ranges back onto the stack until all parts are sorted.