Free tutorials & notes in Hindi & English · Clean code examples · Mobile friendly learning
🔴 Advanced  ·  Lesson 59

STL Algorithms

Written and reviewed by · Senior IT Faculty · 15+ years’ experience

The STL Algorithm Model

Standard algorithms separate what operation to perform from how data is stored. A container owns elements; iterators describe a range; an algorithm reads or modifies that range.

#include <algorithm>
#include <vector>

std::vector<int> values{7, 2, 9, 4};
std::sort(values.begin(), values.end());

The same find or count_if can work with vector, array, deque and many user-defined ranges when their iterators meet the requirements. Algorithms do not magically include their headers; use <algorithm> for most sequence algorithms and <numeric> for accumulation and related numeric operations.

FamilyExamples
Non-modifying queriesfind, count, all_of
Copy/transformcopy, transform, replace
Reorderingreverse, rotate, shuffle
Sorting/searchingsort, lower_bound, binary_search
Numericaccumulate, iota, inner_product

Start with the STL architecture guide if containers and iterators are new.

Iterator Ranges, Requirements and C++20 Ranges

Classic algorithms usually accept [first,last). The first position is included; last is one past the range and must not be dereferenced.

auto first = values.begin();
auto last = values.end();
std::reverse(first, last);
AlgorithmImportant iterator requirement
find/countInput iterator
copyReadable input + writable output
reverseBidirectional iterator
sort/nth_elementRandom-access iterator

This explains why std::sort works with vector but not list. Study iterator categories for the complete model.

C++20 range algorithms can accept a whole range and use projections:

#include <ranges>

struct Student { std::string name; int mark; };
std::ranges::sort(students, std::greater{}, &Student::mark);

Many ranges algorithms return structured result types rather than a single iterator. Views may be lazy and often refer to another range, so the source lifetime must outlast view use.

Searching, Counting and Predicates

auto found = std::find(values.begin(), values.end(), 9);
if (found != values.end()) {
    std::cout << "Index: " << std::distance(values.begin(), found);
}

const auto evens = std::count_if(values.begin(), values.end(),
                                 [](int n) { return n % 2 == 0; });
const bool all_positive = std::all_of(values.begin(), values.end(),
                                      [](int n) { return n > 0; });
AlgorithmMeaning
find/find_ifFirst matching position or end
count/count_ifNumber of matches
all_ofEvery element satisfies predicate
any_ofAt least one satisfies predicate
none_ofNo element satisfies predicate
mismatchFirst differing pair

A predicate must not invalidate the range or unpredictably modify values used by the algorithm. Capture only what is needed and prefer pure, readable lambdas.

Copy, Transform, Replace and Remove

std::vector<int> doubled(values.size());
std::transform(values.begin(), values.end(), doubled.begin(),
               [](int n) { return n * 2; });

std::replace(values.begin(), values.end(), -1, 0);
std::reverse(values.begin(), values.end());

The destination of copy/transform must have enough space, or use an insertion iterator:

std::vector<int> result;
result.reserve(values.size());
std::copy_if(values.begin(), values.end(),
             std::back_inserter(result),
             [](int n) { return n >= 0; });

Erase–remove correctly

auto new_end = std::remove_if(values.begin(), values.end(),
                              [](int n) { return n < 0; });
values.erase(new_end, values.end());

// C++20 container convenience:
std::erase_if(values, [](int n) { return n < 0; });

remove_if does not erase container elements; it moves retained values forward and returns the logical end. Using only the first line leaves a valid but unspecified tail.

Sorting, Comparators and Binary Search

std::sort(values.begin(), values.end());
const bool has_75 = std::binary_search(values.begin(), values.end(), 75);
auto first_75 = std::lower_bound(values.begin(), values.end(), 75);
auto after_75 = std::upper_bound(values.begin(), values.end(), 75);
AlgorithmPurpose
sortOrder range; equal order not preserved
stable_sortPreserve relative order of equivalent elements
partial_sortSort the first selected part
nth_elementPlace nth element as in sorted order; sides partitioned
lower_boundFirst position not ordered before value
equal_rangeRange of equivalent values

A comparator must impose strict weak ordering. Use a < b, not a <= b. Binary-search algorithms require a range partitioned according to a compatible ordering; calling them on arbitrary unsorted data violates their precondition.

std::sort(students.begin(), students.end(),
          [](const Student& a, const Student& b) {
              if (a.mark != b.mark) return a.mark > b.mark;
              return a.name < b.name;
          });

Numeric Algorithms and Type Safety

#include <numeric>

const long long total = std::accumulate(values.begin(), values.end(), 0LL);
std::vector<int> ids(5);
std::iota(ids.begin(), ids.end(), 101); // 101 102 103 104 105

The initial value in accumulate determines the accumulation type. Using 0 accumulates as int; use 0LL for a wider integer sum or 0.0 for floating point when appropriate.

AlgorithmUse
accumulateFold values from an initial value
iotaFill with increasing values
inner_productPairwise products and sum/generalized fold
partial_sumRunning totals
adjacent_differenceDifferences between neighbors
reduceReduction that may reorder operations
Floating point: reordered reduction can produce a different rounding result. Do not substitute reduce for accumulate when operation order is semantically required.

Complete Student-Score Analysis with Output

#include <algorithm>
#include <functional>
#include <iostream>
#include <numeric>
#include <vector>

int main() {
    std::vector<int> scores{64, 91, 75, 52, 88};
    const int total = std::accumulate(scores.begin(), scores.end(), 0);
    const auto passed = std::count_if(scores.begin(), scores.end(),
                                      [](int score) { return score >= 75; });

    std::sort(scores.begin(), scores.end(), std::greater<>{});

    std::cout << "Descending:";
    for (int score : scores) std::cout << ' ' << score;
    std::cout << "\nPass count: " << passed
              << "\nAverage: " << total / static_cast<double>(scores.size());
}
Descending: 91 88 75 64 52 Pass count: 3 Average: 74

Total is 370, so the floating-point average is exactly 74 for this dataset. The comparator orders descending, and the pass predicate includes 75.

Common Mistakes, Practice and Review

MistakeCorrection
binary_search on unsorted inputEstablish compatible partition/order first
Using sort on listUse list::sort or proper container
Dereferencing returned endCompare with end before access
Destination has no spaceResize or use back_inserter
remove expected to shrink vectorErase returned tail
Comparator uses <=Strict weak ordering
Wrong accumulate initial typeChoose 0LL/0.0 intentionally
Mutating range inside predicateKeep callback valid and stable

Practice: sort Student records by two keys, find first failing mark, remove invalid scores, calculate running totals, obtain top three with partial_sort, and compare classic algorithms with C++20 ranges.

  1. Correct header?
  2. Valid half-open range?
  3. Iterator category sufficient?
  4. Ordering precondition satisfied?
  5. Comparator/predicate valid?
  6. Output destination large enough?
  7. Returned iterator checked?
  8. Numeric result type deliberate?

Authoritative References

Iterator requirements, ordering preconditions and algorithm behavior were checked against the current working draft. Practice them with the complete vector tutorial and sorting/searching lesson.

STL Algorithm Model

Container elements own करता है, iterators range बताते हैं और algorithm operation करता है। इससे same find/count_if कई suitable containers पर reusable होता है।

std::vector<int> values{7,2,9,4};
std::sort(values.begin(),values.end());
FamilyExamples
Queriesfind, count, all_of
Transformcopy, transform, replace
Reorderreverse, rotate, shuffle
Sort/searchsort, lower_bound
Numericaccumulate, iota

Most algorithms के लिए <algorithm>, numeric के लिए <numeric> direct include करें। STL guide देखें।

Ranges और Iterator Requirements

[first,last) first include और last exclude करती है; end को dereference न करें।

AlgorithmIterator
find/countInput
copyReadable + writable output
reverseBidirectional
sortRandom access

इसलिए std::sort vector पर चलता है, list पर नहीं। C++20 range algorithms whole range और projection ले सकते हैं:

std::ranges::sort(students,std::greater{},&Student::mark);

Lazy views source को refer कर सकती हैं; source lifetime पर्याप्त हो। iterators पढ़ें।

Search, Count और Predicates

auto found=std::find(values.begin(),values.end(),9);
if(found!=values.end()) std::cout<<*found;
auto evens=std::count_if(values.begin(),values.end(),
 [](int n){return n%2==0;});
bool positive=std::all_of(values.begin(),values.end(),
 [](int n){return n>0;});
  • find/find_if first match या end।
  • count/count_if match count।
  • all_of सभी, any_of कोई एक, none_of कोई नहीं।
  • mismatch first different pair।

Predicate range invalidate न करे; simple, stable lambda रखें।

Transform, Copy और Remove

std::vector<int> doubled(values.size());
std::transform(values.begin(),values.end(),doubled.begin(),
 [](int n){return n*2;});
std::vector<int> result;
std::copy_if(values.begin(),values.end(),
 std::back_inserter(result),[](int n){return n>=0;});

Destination में space हो या insertion iterator लें। Erase-remove:

auto end=std::remove_if(values.begin(),values.end(),
 [](int n){return n<0;});
values.erase(end,values.end());
// C++20: std::erase_if(values,predicate);

remove_if vector size नहीं घटाता; logical end देता है।

Sorting और Binary Search

std::sort(values.begin(),values.end());
bool found=std::binary_search(values.begin(),values.end(),75);
auto first=std::lower_bound(values.begin(),values.end(),75);
  • sort equal order preserve नहीं करता।
  • stable_sort equivalent order preserve करता है।
  • partial_sort selected first part sort करता है।
  • nth_element nth को sorted position पर रखता है।
  • lower/upper_bound equivalent range की boundaries देते हैं।

Comparator strict weak ordering दे; <= गलत। Binary search के लिए compatible ordering/partition जरूरी है।

Numeric Algorithms और Types

long long total=std::accumulate(values.begin(),values.end(),0LL);
std::vector<int> ids(5);
std::iota(ids.begin(),ids.end(),101);

accumulate का initial value result type तय करता है: large integer sum में 0LL और floating case में 0.0 सोचकर चुनें।

AlgorithmUse
accumulateFold/sum
iotaIncreasing fill
inner_productPairwise fold
partial_sumRunning totals
reduceMay reorder operations
Floating-point rounding/order important हो तो reduce को accumulate का automatic replacement न मानें।

Complete Score Analysis और Output

std::vector<int> scores{64,91,75,52,88};
int total=std::accumulate(scores.begin(),scores.end(),0);
auto passed=std::count_if(scores.begin(),scores.end(),
 [](int s){return s>=75;});
std::sort(scores.begin(),scores.end(),std::greater<>{});
Descending: 91 88 75 64 52 Pass count: 3 Average: 74

Total 370 है। Pass predicate 75 include करता और comparator descending order देता है।

Mistakes, Practice और Review

MistakeCorrection
Unsorted binary searchCompatible order
list पर std::sortlist::sort
Returned end dereferenceCheck first
Destination no spaceResize/back_inserter
remove shrinks vectorErase tail
Comparator <=Strict weak order
Initial type wrong0LL/0.0

Practice: Student two-key sort, first failing mark, invalid score removal, running totals, top three और ranges comparison।

  1. Header?
  2. Valid range?
  3. Iterator capability?
  4. Precondition?
  5. Comparator?
  6. Destination?
  7. Return checked?
  8. Numeric type?

Authoritative संदर्भ

Requirements और preconditions current draft से verified हैं। vector तथा sorting/searching पर practice करें।

अक्सर पूछे जाने वाले प्रश्न (FAQ)

C++ STL algorithms क्या हैं?
ये reusable standard-library function templates हैं जो iterator ranges या C++20 range objects पर search, count, copy, transform, partition और sort करते हैं।
Algorithms [first,last) range क्यों लेते हैं?
Half-open range first include और last exclude करती है। Empty range natural बनती है, adjacent ranges compose होती हैं और distance element count देता है।
क्या std::sort को std::list पर लगा सकते हैं?
नहीं। std::sort को random-access iterators चाहिए, जबकि list bidirectional iterators देती है। list::sort या suitable random-access container लें।
binary_search या lower_bound से पहले sorting जरूरी है?
Range same ordering के अनुसार partitioned होनी चाहिए; ordinary use में compatible comparator से sorted होना जरूरी है।
erase-remove idiom क्या है?
remove/remove_if retained elements compact करके logical end देता है, container छोटा नहीं करता। Trailing range erase करें या available होने पर std::erase_if लें।
← Back to C++ Tutorial
🔗

Share this topic with a friend

यह topic किसी दोस्त को भेजें

Found it useful? Send it to a classmate learning the same thing.

अच्छा लगा? जो दोस्त यही सीख रहा है, उसे भेज दीजिए।