In C++, the standard template library (STL) offers a robust set of fundamental functions under the <algorithm> header. These functions are beneficial for various tasks involving sequences like arrays, vectors, lists, and different types of containers. Algorithm functions are versatile and work with iterators, enabling their application across multiple container varieties.
Types of Algorithm
There are primarily two categories of algorithms. These include:
- Immutable Algorithms
- Mutable Algorithms
Now, we will discuss these algorithms one by one.
Non-Mutating Algorithms
In C++, non-modifying algorithms function on a series of elements while maintaining their original values. They are primarily employed for performing searches, comparisons, and examinations on different elements. These algorithms are ideal for fetching data without altering the container's contents. Popular instances comprise of find, used to search for a specific value, and count, which tallies the occurrences of a particular element.
These functions are effective, maintain data integrity, and serve as essential utilities for examining or validating elements within STL containers like vectors, linked lists, and arrays.
Mutating Algorithms
In C++, mutating algorithms refer to those algorithms that modify or reorganize the elements within a specified range. Unlike non-mutating algorithms, these operations directly change the original container without generating a new one. The C++ standard library offers a variety of mutating algorithms including functions like sort, reverse, rotate, partition, remove, and more. These algorithms are frequently employed for performing in-place data manipulations with high efficiency.
Member Functions of C++ Algorithm
Here is a compilation of all the member functions available for maps:
Standard Non-Modifying Sequence Algorithms
The provided table displays various typical non-altering sequence functions applied in C++ Algorithms.
| Function | Description |
|---|---|
| all_of | This function is used to tests a condition to all the elements of the range. |
| any_of | This function is used to tests a condition to some or any of the elements of the range |
| none_of | This function is used to checks if none of the elements follow the condition or not. |
| for_each | The function applies an operation to all the elements of the range. |
find |
The function finds a value in the range. |
| find_if | The function finds for an element in the range. |
| findifnot | The function finds an element in the range but in the opposite way as the above one. |
| find_end | The function is used to return the last element of the range. |
| findfirstof | The function finds for the element that satisfies a condition and occurs at the first. |
| adjacent_find | The function makes a search for finding the equal and adjacent elements in a range. |
| count | The function returns the count of a value in the range. |
| count_if | The function returns the count of values that satisfy a condition. |
| mismatch | The function returns the value in sequence which is the first mismatch. |
| equal | The function is used to check if the two ranges have all elements equal. |
| is_permutation | The function checks whether the range in reference is a permutation of some other range. |
| search | The function searches for the subsequence in a range. |
| search_n | The function searches the range for the occurrence of an element. |
C++ Non-Modifying Sequence Operations Example
Let's consider a scenario to demonstrate the unaltered sequence operations in C++.
Example
#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric> // for iota function
using namespace std; //using standard namespace
int main() { //main function
vector<int> data = {2, 4, 6, 8, 10, 3, 4, 6, 8, 10};
// all_of
bool allEven = all_of(data.begin(), data.end(), [](int x){ return x % 2 == 0; });
cout << "All elements are even? " << boolalpha << allEven << endl;
// any_of
bool anyOdd = any_of(data.begin(), data.end(), [](int x){ return x % 2 != 0; });
cout << "Any element is odd? " << boolalpha << anyOdd << endl;
// none_of
bool noneNegative = none_of(data.begin(), data.end(), [](int x){ return x < 0; });
cout << "No negative elements? " << boolalpha << noneNegative << endl;
// for_each
cout << "Elements: ";
for_each(data.begin(), data.end(), [](int x){ cout << x << " "; });
cout << endl;
// find
auto it1 = find(data.begin(), data.end(), 6);
if (it1 != data.end())
cout << "First occurrence of 6 found at index: " << distance(data.begin(), it1) << endl;
// find_if
auto it2 = find_if(data.begin(), data.end(), [](int x){ return x > 8; });
if (it2 != data.end())
cout << "First element > 8 is: " << *it2 << endl;
// find_if_not
auto it3 = find_if_not(data.begin(), data.end(), [](int x){ return x % 2 == 0; });
if (it3 != data.end())
cout << "First non-even element: " << *it3 << endl;
// find_end
vector<int> sub1 = {4, 6};
auto it4 = find_end(data.begin(), data.end(), sub1.begin(), sub1.end());
if (it4 != data.end())
cout << "Last occurrence of {4, 6} starts at index: " << distance(data.begin(), it4) << endl;
// find_first_of
vector<int> targets = {3, 7, 9};
auto it5 = find_first_of(data.begin(), data.end(), targets.begin(), targets.end());
if (it5 != data.end())
cout << "First matching element from {3,7,9} is: " << *it5 << endl;
// adjacent_find
vector<int> repeated = {1, 2, 3, 3, 4, 5};
auto it6 = adjacent_find(repeated.begin(), repeated.end());
if (it6 != repeated.end())
cout << "First pair of adjacent equal elements: " << *it6 << " and " << *(it6 + 1) << endl;
// count
int count_4 = count(data.begin(), data.end(), 4);
cout << "Count of 4s in data: " << count_4 << endl;
// count_if
int count_gt_5 = count_if(data.begin(), data.end(), [](int x){ return x > 5; });
cout << "Count of elements > 5: " << count_gt_5 << endl;
// mismatch
vector<int> d1 = {1, 2, 3, 4, 5};
vector<int> d2 = {1, 2, 0, 4, 5};
auto [m1, m2] = mismatch(d1.begin(), d1.end(), d2.begin());
cout << "First mismatch: " << *m1 << " vs " << *m2 << endl;
// equal
bool areEqual = equal(d1.begin(), d1.end(), d2.begin());
cout << "Are d1 and d2 equal? " << boolalpha << areEqual << endl;
// is_permutation
vector<int> a = {1, 2, 3};
vector<int> b = {3, 2, 1};
bool isPerm = is_permutation(a.begin(), a.end(), b.begin());
cout << "Is b a permutation of a? " << boolalpha << isPerm << endl;
// search
vector<int> needle = {6, 8};
auto it7 = search(data.begin(), data.end(), needle.begin(), needle.end());
if (it7 != data.end())
cout << "Subsequence {6,8} found at index: " << distance(data.begin(), it7) << endl;
// search_n
auto it8 = search_n(data.begin(), data.end(), 2, 4);
if (it8 != data.end())
cout << "Two consecutive 4s found at index: " << distance(data.begin(), it8) << endl;
return 0;
}
Output:
All elements are even? false
Any element is odd? true
No negative elements? true
Elements: 2 4 6 8 10 3 4 6 8 10
First occurrence of 6 found at index: 2
First element > 8 is: 10
First non-even element: 3
Last occurrence of {4, 6} starts at index: 6
First matching element from {3,7,9} is: 3
First pair of adjacent equal elements: 3 and 3
Count of 4s in data: 2
Count of elements > 5: 6
First mismatch: 3 vs 0
Are d1 and d2 equal? false
Is b a permutation of a? true
Subsequence {6,8} found at index: 2
Modifying Sequence Operations
The provided table displays various modifying sequence operations commonly utilized in C++ Algorithm.
| Function | Description |
|---|---|
copy |
The function copies the range of elements. |
| copy_n | The function copies n elements of the range |
| copy_if | The function copies the elements of the range if a certain condition is fulfilled. |
| copy_backward | The function copies the elements in a backward order |
move |
The function moves the ranges of elements. |
| move_backward | The function moves the range of elements in the backward order |
swap |
The function swaps the value of two objects. |
| swap_ranges | The function swaps the value of two ranges. |
| iter_swap | The function swaps the values of two iterators under reference. |
| transform | The function transforms all the values in a range. |
| replace | The function replaces the values in the range with a specific value. |
| replace_if | The function replaces the value of the range if a certain condition is fulfilled. |
| replace_copy | The function copies the range of values by replacing with an element. |
| replacecopyif | The function copies the range of values by replacing with an element if a certain condition is fulfilled. |
fill |
The function fills the values in the range with a value. |
| fill_n | The function fills the values in the sequence. |
| generate | The function is used for the generation of values of the range. |
| generate_n | The function is used for the generation of values of the sequence. |
| remove | The function removes the values from the range. |
| remove_if | The function removes the values of the range if a condition is fulfilled. |
| remove_copy | The function copies the values of the range by removing them. |
| removecopyif | The function copies the values of the range by removing them if a condition is fulfilled. |
| unique | The function identifies the unique element of the range. |
| unique_copy | The function copies the unique elements of the range. |
| reverse | The function reverses the range. |
| reverse_copy | The function copies the range by reversing values. |
| rotate | The function rotates the elements of the range in left direction. |
| rotate_copy | The function copies the elements of the range which is rotated left. |
| random_shuffle | The function shuffles the range randomly. |
| shuffle | The function shuffles the range randomly with the help of a generator. |
C++ Modifying Sequence Operations Example
Let's consider an example to showcase the manipulation of sequence operations in C++.
Example
#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric> // For iota
#include <random> // For shuffle
using namespace std; //using standard namespace
int main() { //main function
vector<int> original(10);
iota(original.begin(), original.end(), 1); // Fill with 1 to 10
// copy
vector<int> copied(10);
copy(original.begin(), original.end(), copied.begin());
cout << "Copied vector: ";
for (int x : copied) cout << x << " ";
cout << endl;
// copy_if (copy only even numbers)
vector<int> evens;
copy_if(original.begin(), original.end(), back_inserter(evens), [](int x) { return x % 2 == 0; });
cout << "Even elements (copy_if): ";
for (int x : evens) cout << x << " ";
cout << endl;
// transform (multiply each element by 2)
vector<int> doubled(10);
transform(original.begin(), original.end(), doubled.begin(), [](int x) { return x * 2; });
cout << "Transformed (doubled) vector: ";
for (int x : doubled) cout << x << " ";
cout << endl;
// replace (replace 5 with 99)
vector<int> replaced = original;
replace(replaced.begin(), replaced.end(), 5, 99);
cout << "Replaced 5 with 99: ";
for (int x : replaced) cout << x << " ";
cout << endl;
// remove (remove value 3)
vector<int> removed = original;
auto new_end = remove(removed.begin(), removed.end(), 3);
removed.erase(new_end, removed.end()); // Physically erase
cout << "Removed 3 from vector: ";
for (int x : removed) cout << x << " ";
cout << endl;
// unique (remove adjacent duplicates)
vector<int> with_dupes = {1, 1, 2, 2, 2, 3, 3, 4};
auto last_unique = unique(with_dupes.begin(), with_dupes.end());
with_dupes.erase(last_unique, with_dupes.end());
cout << "After unique(): ";
for (int x : with_dupes) cout << x << " ";
cout << endl;
// reverse
vector<int> reversed = original;
reverse(reversed.begin(), reversed.end());
cout << "Reversed vector: ";
for (int x : reversed) cout << x << " ";
cout << endl;
// rotate (move first 3 elements to end)
vector<int> rotated = original;
rotate(rotated.begin(), rotated.begin() + 3, rotated.end());
cout << "Rotated vector (left by 3): ";
for (int x : rotated) cout << x << " ";
cout << endl;
// swap_ranges (swap original with doubled)
vector<int> swapped1 = original, swapped2 = doubled;
swap_ranges(swapped1.begin(), swapped1.end(), swapped2.begin());
cout << "After swap_ranges(), swapped1: ";
for (int x : swapped1) cout << x << " ";
cout << "\nAfter swap_ranges(), swapped2: ";
for (int x : swapped2) cout << x << " ";
cout << endl;
// shuffle (modern C++11 shuffle)
vector<int> shuffled = original;
random_device rd;
mt19937 g(rd());
shuffle(shuffled.begin(), shuffled.end(), g);
cout << "Shuffled vector: ";
for (int x : shuffled) cout << x << " ";
cout << endl;
return 0;
}
Output:
Copied vector: 1 2 3 4 5 6 7 8 9 10
Even elements (copy_if): 2 4 6 8 10
Transformed (doubled) vector: 2 4 6 8 10 12 14 16 18 20
Replaced 5 with 99: 1 2 3 4 99 6 7 8 9 10
Removed 3 from vector: 1 2 4 5 6 7 8 9 10
After unique(): 1 2 3 4
Reversed vector: 10 9 8 7 6 5 4 3 2 1
Rotated vector (left by 3): 4 5 6 7 8 9 10 1 2 3
After swap_ranges(), swapped1: 2 4 6 8 10 12 14 16 18 20
After swap_ranges(), swapped2: 1 2 3 4 5 6 7 8 9 10
Shuffled vector: 6 9 1 7 4 3 5 8 2 10
Partitions
The provided table displays various partition operations commonly utilized in C++ Algorithm.
| Function | Description |
|---|---|
| is_partitioned | The function is used to deduce whether the range is partitioned or not. |
| partition | The function is used to partition the range. |
| stable_partition | The function partitions the range in two stable halves. |
| partition_copy | The function copies the range after partition. |
| partition_point | The function returns the partition point for a range. |
C++ Partition Operations Example
Let's consider an example to illustrate the partition functions in C++.
Example
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std; //using standard namespace
bool isEven(int x) {
return x % 2 == 0;
}
int main() { //main function
vector<int> data = {1, 2, 3, 4, 5, 6, 7, 8};
// Check if already partitioned
bool alreadyPartitioned = is_partitioned(data.begin(), data.end(), isEven);
cout << "Is the data partitioned (evens first)? " << boolalpha << alreadyPartitioned << endl;
// Apply partition (non-stable)
partition(data.begin(), data.end(), isEven);
cout << "After partition (evens first): ";
for (int x : data) cout << x << " ";
cout << endl;
// Apply stable_partition
vector<int> data2 = {1, 2, 3, 4, 5, 6, 7, 8};
stable_partition(data2.begin(), data2.end(), isEven);
cout << "After stable_partition (evens first, order preserved): ";
for (int x : data2) cout << x << " ";
cout << endl;
// Use partition_copy
vector<int> evens, odds;
evens.resize(data.size());
odds.resize(data.size());
auto result = partition_copy(data.begin(), data.end(),
evens.begin(), odds.begin(), isEven);
evens.resize(distance(evens.begin(), result.first));
odds.resize(distance(odds.begin(), result.second));
cout << "Partitioned copy - evens: ";
for (int x : evens) cout << x << " ";
cout << "\nPartitioned copy - odds: ";
for (int x : odds) cout << x << " ";
cout << endl;
// Use partition_point
auto it = partition_point(data.begin(), data.end(), isEven);
cout << "Partition point index: " << distance(data.begin(), it) << endl;
return 0;
}
Output:
Is the data partitioned (evens first)? false
After partition (evens first): 8 2 6 4 5 3 7 1
After stable_partition (evens first, order preserved): 2 4 6 8 1 3 5 7
Partitioned copy - evens: 8 2 6 4
Partitioned copy - odds: 5 3 7 1
Partition point index: 4
Sorting
The provided table displays various sorting algorithms utilized in C++ Algorithm.
| Function | Description |
|---|---|
sort |
The function sorts all the elements in a range. |
| stable_sort | The function sorts the elements in the range, maintaining the relative equivalent order. |
| partial_sort | The function partially sorts the elements of the range. |
| partialsortcopy | The function copies the elements of the range after sorting it. |
| is_sorted | The function checks whether the range is sorted or not. |
| issorteduntil | The function checks till which element a range is sorted. |
| nth_element | The functions sorts the elements in the range. |
C++ Sorting Operations Example
Let's consider an example to showcase the sorting functionalities in C++.
Example
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std; //using standard namespace
void printVector(const vector<int>& v, const string& msg) {
cout << msg;
for (int x : v) cout << x << " ";
cout << endl;
}
int main() { //main function
vector<int> data = {7, 2, 9, 4, 3, 8, 1, 6, 5};
// 1. sort
vector<int> sorted = data;
sort(sorted.begin(), sorted.end());
printVector(sorted, "Sorted vector: ");
// 2. stable_sort
vector<pair<int, char>> stableData = {{3, 'a'}, {1, 'b'}, {3, 'c'}, {2, 'd'}};
stable_sort(stableData.begin(), stableData.end());
cout << "Stable sorted vector of pairs: ";
for (auto& p : stableData) cout << "(" << p.first << "," << p.second << ") ";
cout << endl;
// 3. partial_sort (smallest 5 elements)
vector<int> partial = data;
partial_sort(partial.begin(), partial.begin() + 5, partial.end());
printVector(partial, "Partially sorted (first 5 smallest): ");
// 4. partial_sort_copy
vector<int> dest(5);
partial_sort_copy(data.begin(), data.end(), dest.begin(), dest.end());
printVector(dest, "Partial sort copy (5 smallest): ");
// 5. is_sorted
bool sortedStatus = is_sorted(sorted.begin(), sorted.end());
cout << "Is the sorted vector actually sorted? " << boolalpha << sortedStatus << endl;
// 6. is_sorted_until
vector<int> partlySorted = {1, 2, 3, 7, 5, 6};
auto until = is_sorted_until(partlySorted.begin(), partlySorted.end());
cout << "is_sorted_until found unsorted at position: "
<< distance(partlySorted.begin(), until) << endl;
// 7. nth_element (place the 5th smallest element in correct position)
vector<int> nth = data;
nth_element(nth.begin(), nth.begin() + 4, nth.end()); // 5th smallest
printVector(nth, "After nth_element (5th smallest in correct place): ");
cout << "5th smallest element is: " << nth[4] << endl;
return 0;
}
Output:
Sorted vector: 1 2 3 4 5 6 7 8 9
Stable sorted vector of pairs: (1,b) (2,d) (3,a) (3,c)
Partially sorted (first 5 smallest): 1 2 3 4 5 9 8 7 6
Partial sort copy (5 smallest): 1 2 3 4 5
Is the sorted vector actually sorted? true
is_sorted_until found unsorted at position: 4
After nth_element (5th smallest in correct place): 3 2 1 4 5 7 6 9 8
5th smallest element is: 5
Binary Search
The provided table displays various binary search functions commonly utilized in C++ Algorithm.
| Function | Description |
|---|---|
| lower_bound | Returns the lower bound element of the range. |
| upper_bound | Returns the upper bound element of the range. |
| equal_range | The function returns the subrange for the equal elements. |
| binary_search | The function tests if the values in the range exist in a sorted sequence or not. |
C++ Binary Search Operations Example
Let's consider a scenario to illustrate the binary search procedures in C++.
Example
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std; //using standard namespace
int main() { //main function
vector<int> data = {1, 3, 3, 3, 5, 7, 9, 11};
// Must be sorted before using binary search algorithms
cout << "Sorted data: ";
for (int x : data) cout << x << " ";
cout << endl;
int value = 3;
// 1. binary_search
bool found = binary_search(data.begin(), data.end(), value);
cout << "Is value " << value << " present? " << boolalpha << found << endl;
// 2. lower_bound
auto lower = lower_bound(data.begin(), data.end(), value);
cout << "Lower bound of " << value << " is at index: " << distance(data.begin(), lower)
<< ", value: " << *lower << endl;
// 3. upper_bound
auto upper = upper_bound(data.begin(), data.end(), value);
cout << "Upper bound of " << value << " is at index: " << distance(data.begin(), upper)
<< ", value: " << *upper << endl;
// 4. equal_range
auto range = equal_range(data.begin(), data.end(), value);
cout << "Equal range of " << value << " is from index "
<< distance(data.begin(), range.first) << " to "
<< distance(data.begin(), range.second) << endl;
cout << "Elements in equal range: ";
for (auto it = range.first; it != range.second; ++it)
cout << *it << " ";
cout << endl;
return 0;
}
Output:
Sorted data: 1 3 3 3 5 7 9 11
Is value 3 present? true
Lower bound of 3 is at index: 1, value: 3
Upper bound of 3 is at index: 4, value: 5
Equal range of 3 is from index 1 to 4
Elements in equal range: 3 3 3
Merge
The provided table displays various merge operations commonly utilized in C++ Algorithm.
Merge
| Function | Description |
|---|---|
| merge | The function merges two ranges that are in a sorted order. |
| inplace_merge | The function merges two consecutive ranges that are sorted. |
| includes | The function searches whether the sorted range includes another range or not. |
| set_union | The function returns the union of two ranges that are sorted. |
| set_intersection | The function returns the intersection of two ranges that are sorted. |
| set_difference | The function returns the difference of two ranges that are sorted. |
| setsymmetricdifference | The function returns the symmetric difference of two ranges that are sorted. |
C++ Merge Operations Example
Let's consider an example to illustrate the merging operations in C++.
Example
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std; //using standard namespace
void printVector(const vector<int>& v, const string& msg) {
cout << msg;
for (int x : v) cout << x << " ";
cout << endl;
}
int main() { //main function
vector<int> A = {1, 3, 5, 7};
vector<int> B = {2, 3, 6, 8};
// 1. merge
vector<int> merged(A.size() + B.size());
merge(A.begin(), A.end(), B.begin(), B.end(), merged.begin());
printVector(merged, "Merged A and B: ");
// 2. inplace_merge
vector<int> C = {1, 3, 5, 7, 2, 4, 6};
inplace_merge(C.begin(), C.begin() + 4, C.end());
printVector(C, "After inplace_merge: ");
// 3. includes
vector<int> superset = {1, 2, 3, 4, 5};
vector<int> subset = {2, 4};
bool result = includes(superset.begin(), superset.end(), subset.begin(), subset.end());
cout << "Does superset include subset? " << boolalpha << result << endl;
// 4. set_union
vector<int> unionResult(A.size() + B.size());
auto it1 = set_union(A.begin(), A.end(), B.begin(), B.end(), unionResult.begin());
unionResult.resize(it1 - unionResult.begin());
printVector(unionResult, "Set union: ");
// 5. set_intersection
vector<int> intersectionResult(min(A.size(), B.size()));
auto it2 = set_intersection(A.begin(), A.end(), B.begin(), B.end(), intersectionResult.begin());
intersectionResult.resize(it2 - intersectionResult.begin());
printVector(intersectionResult, "Set intersection: ");
// 6. set_difference (A - B)
vector<int> differenceResult(A.size());
auto it3 = set_difference(A.begin(), A.end(), B.begin(), B.end(), differenceResult.begin());
differenceResult.resize(it3 - differenceResult.begin());
printVector(differenceResult, "Set difference (A - B): ");
// 7. set_symmetric_difference
vector<int> symmetricDiffResult(A.size() + B.size());
auto it4 = set_symmetric_difference(A.begin(), A.end(), B.begin(), B.end(), symmetricDiffResult.begin());
symmetricDiffResult.resize(it4 - symmetricDiffResult.begin());
printVector(symmetricDiffResult, "Set symmetric difference: ");
return 0;
}
Output:
Merged A and B: 1 2 3 3 5 6 7 8
After inplace_merge: 1 2 3 4 5 6 7
Does superset include subset? true
Set union: 1 2 3 5 6 7 8
Set intersection: 3
Set difference (A - B): 1 5 7
Set symmetric difference: 1 2 5 6 7 8
The provided table displays various heap functions commonly employed in C++ Algorithm.
| Function | Description |
|---|---|
| push_heap | The function pushes new elements in the heap. |
| pop_heap | The function pops new elements in the heap. |
| make_heap | The function is used for the creation of a heap. |
| sort_heap | The function sorts the heap. |
| is_heap | The function checks whether the range is a heap. |
| isheapuntil | The function checks till which position a range is a heap. |
C++ Heap Operations Example
Let's consider an illustration to showcase the heap manipulations in C++.
Example
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std; //using standard namespace
void printVector(const vector<int>& v, const string& msg) {
cout << msg;
for (int x : v) cout << x << " ";
cout << endl;
}
int main() { //main function
vector<int> heap = {10, 20, 30, 5, 15};
// 1. make_heap
make_heap(heap.begin(), heap.end());
printVector(heap, "Heap after make_heap: "); // Heapify the vector
// 2. push_heap (insert new element into heap)
heap.push_back(25); // Add new element at the end
push_heap(heap.begin(), heap.end());
printVector(heap, "Heap after push_heap(25): ");
// 3. pop_heap (remove root of heap)
pop_heap(heap.begin(), heap.end()); // Moves the largest to the end
cout << "Popped element: " << heap.back() << endl;
heap.pop_back(); // Actually remove the last element
printVector(heap, "Heap after pop_heap: ");
// 4. is_heap
bool result = is_heap(heap.begin(), heap.end());
cout << "Is the vector a heap? " << boolalpha << result << endl;
// 5. is_heap_until
vector<int> testHeap = {30, 20, 25, 10, 15, 5, 40}; // not a valid heap
auto it = is_heap_until(testHeap.begin(), testHeap.end());
cout << "is_heap_until fails at index: " << distance(testHeap.begin(), it) << endl;
// 6. sort_heap (converts heap into sorted array)
sort_heap(heap.begin(), heap.end());
printVector(heap, "Heap after sort_heap (sorted array): ");
return 0;
}
Output:
Heap after make_heap: 30 20 10 5 15
Heap after push_heap(25): 30 20 25 5 15 10
Popped element: 30
Heap after pop_heap: 25 20 10 5 15
Is the vector a heap? true
is_heap_until fails at index: 6
Heap after sort_heap (sorted array): 5 10 15 20 25
Min/Max
The provided table displays various minimum and maximum operations commonly utilized in C++ Algorithm.
| Function | Description |
|---|---|
min |
Returns the smallest element of the range. |
max |
Returns the largest element of the range. |
| minmax | Returns the smallest and largest element of the range. |
| min_element | Returns the smallest element of the range. |
| max_element | Returns the largest element of the range. |
| minmax_element | Returns the smallest and largest element of the range. |
C++ Min/Max Operations Example
Let's consider a scenario to illustrate the minimum and maximum operations in C++.
Example
#include <iostream>
#include <vector>
#include <algorithm>
#include <utility> // for std::pair
using namespace std; //using standard namespace
int main() { //main function
vector<int> nums = {12, 45, 23, 67, 34, 89, 11, 9};
// 1. min (between two values)
int a = 10, b = 20;
cout << "min(10, 20): " << min(a, b) << endl;
// 2. max (between two values)
cout << "max(10, 20): " << max(a, b) << endl;
// 3. minmax (between two values)
auto minmaxVal = minmax(a, b);
cout << "minmax(10, 20): (" << minmaxVal.first << ", " << minmaxVal.second << ")" << endl;
// 4. min_element (smallest element in the vector)
auto minIt = min_element(nums.begin(), nums.end());
cout << "Minimum element in vector: " << *minIt << " at index " << distance(nums.begin(), minIt) << endl;
// 5. max_element (largest element in the vector)
auto maxIt = max_element(nums.begin(), nums.end());
cout << "Maximum element in vector: " << *maxIt << " at index " << distance(nums.begin(), maxIt) << endl;
// 6. minmax_element (returns both min and max from range)
auto minmaxIt = minmax_element(nums.begin(), nums.end());
cout << "Minmax in vector: min = " << *minmaxIt.first << ", max = " << *minmaxIt.second << endl;
return 0;
}
Output:
min(10, 20): 10
max(10, 20): 20
minmax(10, 20): (10, 20)
Minimum element in vector: 9 at index 7
Maximum element in vector: 89 at index 5
Minmax in vector: min = 9, max = 89
Other Functions
The provided table displays various additional functions that are beneficial in C++ Algorithm.
| Function | Description |
|---|---|
| lexicographical_comapre | The function performs the lexicographical less-than comparison. |
| next_permutation | The function is used for the transformation of the range into the next permutation. |
| perv_permutation | The function is used for the transformation of the range into the previous permutation. |
Key features of C++ Algorithm Functions
There are several key features of C++ algorithm functions. Some main features are as follows:
- Generic and template-based: C++ algorithm functions are template-based, which allows them to work without re-writing with various data types and container types (such as vector, list, and array).
- Modifying and Non-Modifying Categories: The algorithm is grouped into non-modifying (such as find, count, and for_each) and modified (such as copy, replace, and transform) whether they change input data.
- Custom condition support: Many specific terms (eg, findif, countif) to define predicate functions or Lambdas, increase custom logic.
- Efficient and optimized: STL algorithms are adapted for performance and usually provide guaranteed time complexity (such as sort uses a hybrid sorting algorithm with complexity O(n log n).
- Do not resize containers: Algorithm containers do not manage size or memory.
Conclusion
In summary, the C++ algorithm function serves as a vital set of tools for effective and expressive coding, made accessible via the header within the standard template library (STL). These functions encapsulate intricate low-level iteration processes and offer tailored, clear-cut functionalities for activities like data searching, sorting, altering, comparing, and converting.
C++ Algorithm FAQs
1) What is the purpose of the __PRESERVE_17__ header in C++?
In C++, the <algorithm> header offers a diverse range of predefined functions for tasks like sorting, searching, counting, and altering data. This header streamlines the code by substituting repetitive code with reusable algorithms. These functions interact seamlessly with containers through iterators, enhancing the clarity, performance, and abstraction of C++ programming.
2) Do C++ algorithm functions work with all types of containers?
Algorithm functions work on iterators rather than containers directly, allowing compatibility with various STL containers like vectors, lists, and arrays. This design enhances flexibility in handling tasks. However, certain algorithms mandate specific iterator types, for instance, sort necessitates random-access iterators.
3) What is the difference between std::sort and std::stable_sort?
In C++, the std::sort methods maintain quick and rearranged elements in sequence but do not retain the initial arrangement of identical elements. Conversely, the std::stablesort function preserves the original positions of similar elements, ensuring the order remains intact when necessary. Although sort is faster, stablesort guarantees stability in scenarios involving multiple levels of sorting.
4) How does the algorithm function support the custom logic through predicates or lambdas?
Many algorithms support a user-defined criterion, known as a predicate, which can be a function pointer, functor, or lambda expression. This feature enables the application of custom conditions during various operations like filtering, sorting, and searching. Lambdas are commonly employed for concise and inline logic implementation, fostering a more expressive and functional programming approach within C++.
5) Are algorithm functions more efficient than manual loops, and why?
Yes, algorithm functions are typically more personalized and dependable compared to manually written loops. They are integral to the Standard Template Library (STL) and have undergone extensive testing and optimization over the years. This results in code that is easier to comprehend and less prone to errors. By shifting the focus from the iteration process to the desired outcome, developers can write more declarative code.