Back to C++
2026-04-287 min read

C++ Algorithms

Learn C++ Algorithms step by step with clear examples and exercises.

Why This Matters

Welcome to this full guide on C++ algorithms, a crucial topic for competitive programming, coding interviews, and real-world problem-solving. In this tutorial, we will delve into the essential algorithms every C++ programmer should know, along with practical examples, common mistakes, and practice questions to help you master the subject.

Understanding Algorithms' Importance

Algorithms are the backbone of computer science, and understanding them is vital for competitive programming, coding interviews, and real-world problem-solving. C++ provides a robust set of libraries that implement many popular algorithms, making it an ideal choice for competitive programming contests such as Codeforces, Topcoder, and AtCoder.

Prerequisites

To follow this tutorial, you should have a basic understanding of:

  • C++ syntax and data structures (arrays, vectors, linked lists, etc.)
  • Time and space complexity analysis (Big O notation)
  • STL (Standard Template Library) containers and algorithms
  • Vectors, lists, deques, arrays, sets, and maps
  • Familiarity with common data structures like stacks, queues, and priority queues
  • Implementing custom stack and queue classes in C++
  • Knowledge of basic graph theory concepts such as adjacency matrices and adjacency lists
  • Representing graphs using adjacency lists and adjacency matrices
  • Understanding of recursion and dynamic programming concepts

Core Concept

This section will cover the most important algorithms in C++, including:

  1. Sorting Algorithms
  • Bubble Sort
  • Implementation and time complexity analysis
  • Selection Sort
  • Implementation and time complexity analysis
  • Insertion Sort
  • Implementation and time complexity analysis
  • Merge Sort
  • Implementation, time complexity analysis, and recursive vs. iterative approaches
  • Quick Sort
  • Implementation, time complexity analysis, and common pitfalls (e.g., tail-recursion optimization)
  • Heap Sort
  • Implementation and time complexity analysis
  • Radix Sort (for sorting large integers and strings)
  • Implementation and time complexity analysis
  1. Search Algorithms
  • Linear Search
  • Implementation and time complexity analysis
  • Binary Search
  • Implementation, time complexity analysis, and handling edge cases (e.g., empty arrays and unsorted input)
  1. Graph Algorithms
  • Depth-First Search (DFS)
  • Implementation, time complexity analysis, and strong connectivity components
  • Breadth-First Search (BFS)
  • Implementation, time complexity analysis, and single-source shortest paths
  • Dijkstra's Algorithm
  • Implementation, time complexity analysis, and handling negative edge weights
  • Bellman-Ford Algorithm
  • Implementation, time complexity analysis, and detecting negative cycles
  • Floyd-Warshall Algorithm
  • Implementation, time complexity analysis, and finding the shortest paths between all pairs of nodes in a weighted graph
  • Topological Sort
  • Implementation, time complexity analysis, and applications (e.g., scheduling tasks with dependencies)
  1. Dynamic Programming
  • Knapsack Problem
  • 0/1 knapsack, fractional knapsack, and unbounded knapsack problems
  • Longest Common Subsequence (LCS)
  • Implementation using dynamic programming and time complexity analysis
  • Matrix Chain Multiplication
  • Implementation using dynamic programming and time complexity analysis
  1. Greedy Algorithms
  • Huffman Coding
  • Implementation, time complexity analysis, and Huffman tree construction
  • Kruskal's Minimum Spanning Tree
  • Implementation, time complexity analysis, and handling self-loops and multiple edges
  • Activity Selection Problem
  • Implementation, time complexity analysis, and applications (e.g., scheduling activities with overlapping times)
  • Knight's Tour
  • Implementation using depth-first search and backtracking
  1. Divide and Conquer
  • Merge Sort
  • Implementation, time complexity analysis, and recursive vs. iterative approaches
  • Quick Sort
  • Implementation, time complexity analysis, and common pitfalls (e.g., tail-recursion optimization)
  • Binary Exponential Search (faster binary search variant)
  • Implementation and time complexity analysis
  1. Backtracking
  • N-Queens Problem
  • Implementation using backtracking and time complexity analysis
  • Graph Coloring
  • Implementation, time complexity analysis, and applications (e.g., scheduling tasks with resource constraints)
  • Hamiltonian Path/Cycle
  • Implementation using depth-first search and backtracking

Worked Example

To illustrate the concepts discussed, let's walk through a worked example using Quick Sort—a divide-and-conquer algorithm for sorting arrays.

#include <iostream>
using namespace std;

void swap(int arr[], int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}

int partition(int arr[], int low, int high) {
int pivot = arr[high];
int i = (low - 1);

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

void quickSort(int arr[], int low, int high) {
if (low < high) {
int pivotIndex = partition(arr, low, high);

quickSort(arr, low, pivotIndex - 1);
quickSort(arr, pivotIndex + 1, high);
}
}

int main() {
int arr[] = {10, 7, 8, 9, 1, 5};
int n = sizeof(arr) / sizeof(arr[0]);

quickSort(arr, 0, n - 1);

cout << "Sorted array: \n";
for (int i = 0; i < n; i++) {
cout << arr[i] << " ";
}
cout << endl;

return 0;
}

In this example, we implement the Quick Sort algorithm to sort an array of integers. The quickSort() function recursively partitions the input array around a pivot and sorts the subarrays on either side.

Common Mistakes

  • Not handling the edge cases: Ensure you properly handle arrays with one or zero elements, as well as duplicates in the input array.
  • Example: Modifying the partition function to handle duplicate pivot values.
  • Incorrect implementation of algorithms: Carefully review your code to ensure it follows the correct algorithm steps and handles all possible scenarios.
  • Example: Correcting a mistake in the Huffman Coding implementation that causes incorrect frequency calculations.
  • Ignoring time and space complexity: Always analyze the time and space complexity of your solutions to optimize them for competitive programming contests.
  • Example: Optimizing the Quick Sort algorithm by using tail recursion to avoid stack overflow issues.
  • Suboptimal data structures: Using inappropriate data structures can lead to poor performance, especially when dealing with large datasets.
  • Example: Choosing a more efficient data structure (e.g., binary heap instead of array) for implementing the Heap Sort algorithm.
  • Recursion depth limit: Some algorithms have a recursive depth limit that may cause the program to crash or perform poorly if not handled properly.
  • Example: Implementing an iterative version of Quick Sort using a stack to avoid the recursion depth limit.

Practice Questions

  1. Implement Binary Search in C++.
  • Handling edge cases, time complexity analysis, and optimizing for competitive programming contests.
  1. Write a program to find the maximum sum subarray using Kadane's algorithm.
  • Implementing Kadane's algorithm, handling negative numbers, and time complexity analysis.
  1. Implement Dijkstra's Algorithm to find the shortest path between nodes in a graph.
  • Implementing Dijkstra's Algorithm, handling negative edge weights, and time complexity analysis.
  1. Write a program to check if a given number is prime using Sieve of Eratosthenes.
  • Implementing the Sieve of Eratosthenes, optimizing for large numbers, and time complexity analysis.
  1. Implement the Longest Common Subsequence (LCS) problem using dynamic programming.
  • Implementing LCS using dynamic programming, handling empty strings, and time complexity analysis.
  1. Solve the Knapsack Problem using dynamic programming and 0/1 knapsack, as well as fractional knapsack.
  • Implementing both 0/1 knapsack and fractional knapsack, optimizing for large items and weights, and time complexity analysis.
  1. Write a program to find the shortest path in a graph using Bellman-Ford Algorithm.
  • Implementing Bellman-Ford Algorithm, handling negative cycles, and time complexity analysis.
  1. Implement Floyd-Warshall Algorithm to find the shortest paths between all pairs of nodes in a weighted graph.
  • Implementing Floyd-Warshall Algorithm, optimizing for large graphs, and time complexity analysis.
  1. Solve the N-Queens Problem using backtracking.
  • Implementing the N-Queens Problem using backtracking, handling edge cases, and time complexity analysis.
  1. Write a program to find the minimum spanning tree using Kruskal's Algorithm.
  • Implementing Kruskal's Algorithm, handling self-loops and multiple edges, and time complexity analysis.

FAQ

  1. What is Big O notation, and why is it important in algorithms?
  • Big O notation is a mathematical notation used to describe the time complexity of an algorithm. It's essential for understanding how an algorithm performs as the size of the input data grows.
  1. Why are sorting algorithms important in competitive programming?
  • Sorting algorithms play a crucial role in competitive programming because many problems require sorted arrays or lists to be processed efficiently.
  1. What is the difference between DFS and BFS, and when should I use each algorithm?
  • Depth-First Search (DFS) explores as far as possible along each branch before backtracking, while Breadth-First Search (BFS) explores all nodes at a given depth level before moving on to the next level. Use DFS for problems that require traversing the graph in a specific order or finding a path between two nodes, and use BFS for problems that require finding the shortest path or checking connectivity within the graph.
  1. What is dynamic programming, and how does it help solve problems?
  • Dynamic programming is an algorithmic technique that breaks down complex problems into smaller subproblems, solves each subproblem only once, and stores the solutions to reuse them when needed. This approach helps solve problems more efficiently by avoiding redundant computations.
  1. What are some common data structures used in algorithms?
  • Common data structures include arrays, linked lists, stacks, queues, priority queues, heaps, trees, and graphs. Understanding these data structures is essential for implementing efficient algorithms.
C++ Algorithms | C++ | XQA Learn