Contents

All algorithm in C++

Content

Algorithm Overview

* –> new feature from C++11

Algorithm NameUsageMutating?Head FileComplexity
accumulateAccumulate values in rangeNnumericO(n)
adjacent_differenceCompute adjacent difference of range and return to another placeNnumericO(n)
adjacent_findFind first equal adjacent elements in rangeNalgorithmO(n)
all_of*Test condition on all elements in rangeNalgorithmO(n)
any_of*Test if any element in range fulfills conditionNalgorithmO(n)
binary_searchTest if value exists in sorted sequenceNalgorithmOn average O(logn + 2). On non-random-access iterator is O(n)
copyCopy range of elementsN(copy)algorithmO(n)
copy_backwardCopy range of elements backwardN(copy)algorithmO(n)
copy_if*Copy certain elements of rangeN(copy)algorithmO(n)
copy_n*Copies the first n elements from the range beginningN(copy)algorithmO(n)
countCount appearances of value in rangeNalgorithmO(n)
count_ifReturn number of elements in range satisfying conditionNalgorithmO(n)
equalTest whether the elements in two ranges are equalNalgorithmO(n)
equal_rangeGet sub range of equal elementsNalgorithmO(2logn + 1) for random access iterator, otherwise O(n)
fillFill range with valueYalgorithmO(n)
fill_nAssigns val to the first n elements of the sequence pointed by firstYalgorithmO(n)
findFind the first element in rangeNalgorithmO(n)
find_endFind last subsequence in rangeNalgorithmO(m*(1+n-m))
find_first_ofReturns an iterator to the first element in the range [first1,last1) that matches any of the elements in [first2,last2)NalgorithmO(nm)
find_ifFind the first element in range in some conditionNalgorithmO(n)
find_if_not*Find the first element in range in some conditionNalgorithmO(n)
for_eachApply function to rangeNalgorithmO(n)
generateAssigns the value returned by successive calls to gen to the elements in the range [first,last)YalgorithmO(n)
generate_nAssigns the value returned by successive calls to gen to the first n elements of the sequence pointed by firstYalgorithmO(n)
includesTest whether sorted range includes another sorted rangeNalgorithmO(n)
inner_productCompute cumulative inner product of rangeNnumericO(n)
inplace_mergeMerge consecutive sorted rangesYalgorithmO(n) if extra memory is available, otherwise is O(nlogn)
iotaStore increasing sequenceYnumericO(n)
is_heap*Test if range is heapNalgorithmO(n)
is_heap_until*Find first element not in heap order.NalgorithmO(n)
is_partitioned*Test whether range is partitionedYalgorithmO(n)
is_permutation*Compares the elements in the range [first1,last1) with those in the range beginning at first2, and returns true if they just different permutationNalgorithmO(n)
is_sorted*Check whether range is sortedNalgorithmO(n)
is_sorted_until*Find first unsorted element in rangeNalgorithmO(n)
iter_swapSwaps the elements pointed to by a and bYalgorithmO(1)
lexicographical_compareCompare two range lexicographically.NalgorithmO(n)
lower_bondReturn iterator to lower boundNalgorithmO(logn + 1) for random access iterator, otherwise O(n)
make_heapMake heap from rangeYalgorithmO(3n)
maxReturns the largest of a and b. If both are equivalent, a is returned.NalgorithmO(1)
max_elementReturn largest element in rangeNalgorithmO(n)
mergeMerge sorted rangesYalgorithmO(n)
minReturns the smallest of a and b. If both are equivalent, a is returned.NalgorithmO(1)
minmax*Return smallest and largest elements from give 2 value or initializerNalgorithmO(1)
minmax_element*Return smallest and largest elements in rangeNalgorithmO(n)
min_elementReturn smallest element in rangeNalgorithmO(n)
mismatchReturn first position where two ranges differNalgorithmO(n)
move*Move range of elementsYalgorithmO(n)
move_backward*Move range of elements backwardYalgorithmO(n)
next_permutationRearranges the elements in the range [first,last) into the next lexicographically greater permutationYalgorithmO(n)
none_of*Test if no elements fulfill conditionNalgorithmO(n)
nth_elementFind the nth element and put it the exact palce.(quick select)YalgorithmO()
partial_sortPartially sort elements in range while the remaining elements are left without any orderYalgorithmO(mlogn)
partial_sort_copyCopy and partially sort rangeY (if in-place)algorithmO(mlogn)
partial_sumCompute partial sums of range and return to another placeNnumericO(n)
partitionPartition range in two and the iterator returned points to the first element of the second group.YalgorithmO(n)
partition_copy*Partition range into twoNalgorithmO(n)
partition_point*Get partition point and Returns an iterator to the first element in second partNalgorithmO(logn + 2)
pop_heapPop element from heap range. Range shrink and value is at end.YalgorithmO(logn)
prev_permutationRearranges the elements in the range [first,last) into the previous lexicographically-ordered permutation.YalgorithmO(n)
push_heapPush element into heap range. Range extendYalgorithmO(logn)
random_shuffleRandomly rearrange elements in rangeYalgorithmO(n)
removeRemoved element equal to val and returns an iterator to the new end of that range.YalgorithmO(n)
remove_copyRemove and copy to new placeYalgorithmO(n)
remove_copy_ifRemove in a given condition and copyYalgorithmO(n)
remove_ifRemove in a given conditionYalgorithmO(n)
replaceAssigns new_value to all the elements that compare equal to old_valueYalgorithmO(n)
replace_copyReplace and copyYalgorithmO(n)
replace_copy_ifReplace in a given condition and copyYalgorithmO(n)
replace_ifReplace in a given conditionYalgorithmO(n)
reverseReverses the order of the elements in the range [first,last)YalgorithmO(n)
reverse_copyCopies the elements in [first,last) but in reverse orderYalgorithmO(n)
rotateRotates the order of the elements and middle becomes the new first elementYalgorithmO(n)
rotate_copyRotate and copyYalgorithmO(n)
searchSearch range for subsequenceNalgorithmO(n*m)
search_nSearch range for n continue elementsNalgorithmO(n)
set_differenceDifference of two sorted rangesN(copy)algorithmO(2(n+m)-1)
set_intersectionIntersection of two sorted rangesN(copy)algorithmO(2(n+m)-1)
set_symmetric_differenceSymmetric difference of two sorted rangesN(copy)algorithmO(2(n+m)-1)
set_unionUnion of two sorted rangesN(copy)algorithmO(2(n+m)-1)
shuffle*Randomly rearrange elements in range using generatorYalgorithmO(n)
sortSort elements in rangeYalgorithmO(nlogn)
sort_heapSort elements of heapYalgorithmO(nlogn)
stable_partitionPartition range in two - stable orderingYalgorithmO(n) with enough space. Otherwise O(nlogn)
stable_sortSort elements preserving order of equivalentsYalgorithmO(nlogn) with enough space, otherwise O(nlognlogn)
swapExchanges the values of a and bYalgorithmO(1)
swap_rangesExchanges a range of valueYalgorithmO(n)
transformTransform rangeYalgorithmO(n)
uniqueRemove consecutive duplicates in rangeYalgorithmO(n)
unique_copyCopy range removing duplicatesYalgorithmO(n)
upper_bondReturn iterator to upper bound. Since [first, last), the value pointed by the iterator must larger than valNalgorithmO(logn + 1) for random access iterator, otherwise O(n)

Copy

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main(int argc, char const *argv[])
{
	vector<int> iv = {1,2,3,4,5,6};

	vector<int> iv2(6);
	copy(iv.begin(), iv.end(), iv2.begin());
	// iv2: 1 2 3 4 5 6

	vector<int> iv3(3);
	copy_if(iv.begin(), iv.end(), iv3.begin(), [](int a){return a % 2 == 0;});
	// iv3: 2 4 6

	vector<int> iv4(5);
	copy_n(iv.begin(), 5, iv4.begin());
	// iv4: 1 2 3 4 5 6

	vector<int> iv5(6);
	copy_backward(iv.begin(), iv.end(), iv5.end());
	// iv5: 1 2 3 4 5 6

	return 0;
}

Back to top

For each

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main(int argc, char const *argv[])
{
	vector<int> iv = {1,2,3,4,5,6};
	for_each(iv.begin(), iv.end(), [](int x){cout << x << " ";});
	// cout:1 2 3 4 5 6
	return 0;
}

Back to top

Generation

fill fill_n generate generate_n

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

struct StartFrom
{
	int start;
	StartFrom(int s):start(s){};
	int operator() (){return start++;};
};

int main(int argc, char const *argv[])
{
	vector<int> iv1(8); //iv1: 0 0 0 0 0 0 0 0
	fill(iv1.begin(), iv1.begin()+4, 1);
	//iv1: 1 1 1 1 0 0 0 0
	fill_n(iv1.begin()+4, 3, 2);
	//iv1: 1 1 1 1 2 2 2 0

	vector<int> iv2(8); //iv2: 0 0 0 0 0 0 0 0

	StartFrom s1(5);
	generate(iv2.begin(), iv2.begin()+4, s1);
	//iv2: 5 6 7 8 0 0 0 0
	StartFrom s2(10);
	generate_n(iv2.begin()+4, 2, s2);
	//iv2: 5 6 7 8 10 11 0 0

	return 0;
}

Back to top

Heap

Heap algorithm need to cooperate with other container usually vector or array.

More detail about heap: Here

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <iostream>
#include <vector>
#include <algorithm> // heap
#include <functional>
using namespace std;

int main(int argc, char const *argv[]){
    int ia[10] = {0,1,2,3,4,5,6,7,8,9};
    vector<int> iv(ia, ia+10);

    //is_heap
    cout << boolalpha;
    cout << is_heap(iv.begin(), iv.end()) << endl; // false

    // make_heap
    make_heap(iv.begin(), iv.end(), greater<int>()); // 0 1 2 3 4 5 6 7 8 9
    cout << is_heap(iv.begin(), iv.end(), greater<int>()) << endl; // true

    make_heap(iv.begin(), iv.end()); // 9 8 6 7 4 5 2 0 3 1
    cout << is_heap(iv.begin(), iv.end()) << endl; // true

    // pop_heap
    pop_heap(iv.begin(), iv.end()); // 8 7 6 3 4 5 2 0 1 9
    cout << iv.back() << endl; // 9
    iv.pop_back();

    // push_heap
    iv.push_back(99);
    push_heap(iv.begin(), iv.end()); // 99 8 6 3 7 5 2 0 1 4

    // sort_heap
    sort_heap(iv.begin(), iv.end()); // 0 1 2 3 4 5 6 7 8 99

    // Base on array
    make_heap(ia, ia + 10); // 9 8 6 7 4 5 2 0 3 1
    pop_heap(ia, ia + 10);

    // is_heap_until
    // ia: 8 7 6 3 4 5 2 0 1 9
    auto iter = is_heap_until(ia, ia + 10);
    cout << *iter << endl; // 9
    return 0;
}

Back to top

Merge

Sort first!!

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main(int argc, char const *argv[])
{
	// merge
	vector<int> iv1 = {5,10,15,20,25};
	vector<int> iv2 = {50,40,30,20,10};
	vector<int> res1(10);
	sort(iv1.begin(), iv1.end());
	sort(iv2.begin(), iv2.end());

	merge(iv1.begin(), iv1.end(), iv2.begin(), iv2.end(), res1.begin());
	// res: 5 10 10 15 20 20 25 30 40 50

	// inplace_merge
	vector<int> res2(10);
	auto it = copy(iv1.begin(), iv1.end(), res2.begin());
	copy(iv2.begin(), iv2.end(), it);
	// res2: 5 10 15 20 25 10 20 30 40 50

	inplace_merge(res2.begin(), res2.begin() + 5, res2.end());
	// res2: 5 10 10 15 20 20 25 30 40 50

	return 0;
}

Back to top

Move

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;

int main(int argc, char const *argv[])
{
	vector<string> foo = {"air","water","fire","earth"};
	vector<string> bar (4);

	// move
	move(foo.begin(), foo.end(), bar.begin());
	// foo:                     // (for empty string)
	// bar: air water fire earth

	foo = move(bar);
	// foo: air water fire earth
	// bar:    // nothing here.

	// move_backward
	bar.resize(4);
	move_backward(foo.begin(), foo.end(), bar.end());
	// foo:                     // (for empty string)
	// bar: air water fire earth

	// transform
	vector<int> iv1 = {10,20,30,40,50,60};
	vector<int> iv2 = {1,2,3,4,5,6};

	transform(iv1.begin(), iv1.end(), iv2.begin(), [](int a){return ++a;});
	// iv1 + 1 and copy to iv2
	// iv1: 10 20 30 40 50 60
	// iv2: 11 21 31 41 51 61

	transform(iv1.begin(), iv1.end(), iv2.begin(), iv2.begin(), plus<int>());
	// range: ^    ....    ^; opStart: ^; tansform to: ^
	// iv1: 10 20 30 40 50 60
	// iv2: 21 41 61 81 101 121

	return 0;
}

Back to top

Number

<numberic>: iota accumulate inner_product partial_sum adjacent_differenet

<algorithm>: max min max_element min_element minmax count count_if

iota just make a increasing sequence start from a given number.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
#include <iostream>
#include <vector>
#include <numeric>
#include <algorithm>
#include <functional>
#include <utility>
using namespace std;

int main(int argc, char const *argv[])
{
	vector<int> iv(5);

	// iota
	iota(iv.begin(), iv.end(), 1); // 1 2 3 4 5

	// count
	cout << count(iv.begin(), iv.end(), 2) << endl; // 1

	// count_if
	cout << count_if(iv.begin(), iv.end(), [](int a){return a % 2 == 1;}) << endl; // 3

	// accumulate
	cout << accumulate(iv.begin(), iv.end(), 0) << endl; // 15
	// init + *iv + *(iv+1) + ...

	cout << accumulate(iv.begin(), iv.end(), 0, minus<int>()) << endl; // -15
	// init - *iv - *(iv+1) - ...

	// inner_product

	vector<int> iv1 = {10, 20, 30};
	vector<int> iv2 = {1, 2, 3};

	cout << inner_product(iv1.begin(), iv1.end(), iv2.begin(), 0) << endl;
	// 0 + 10 * 1 + 20 * 2 + 30 * 3 = 140

	cout << inner_product(iv1.begin(), iv1.end(), iv2.begin(), 0,
		minus<int>(), divides<int>()) << endl;
	// 0 - 10 / 1 - 20 / 2 - 30 / 3 = -30

	// partial_sum
	vector<int> res(5);
	partial_sum(iv.begin(), iv.end(), res.begin());
	// iv: 1 2 3 4 5
	// res: 1 3 6 10 15

	partial_sum(iv.begin(), iv.end(),res.begin(), minus<int>());
	// iv: 1 2 3 4 5
	// res: 1 -1 -4 -8 -13

	adjacent_difference(iv.begin(), iv.end(), res.begin());
	// iv: 1 2 3 4 5
	// res: 1 1 1 1 1

	adjacent_difference(iv.begin(), iv.end(), res.begin(), multiplies<int>());
	// iv: 1 2 3 4 5
	// res: 1 2 6 12 20

	// adjacent_difference calculate every two adjacent elements
	// y0 = x0
	// y1 = x1 - x0
	// y2 = x2 - x1
	// y3 = x3 - x2
	// y4 = x4 - x3  ...

	// partial_sum calculate all elements b
	// y0 = x0
	// y1 = x0 + x1
	// y2 = x0 + x1 + x2
	// y3 = x0 + x1 + x2 + x3
	// y4 = x0 + x1 + x2 + x3 + x4  ...

	// max
	cout << max(1, 3) << endl; // 3
	cout << max(2, 2) << endl; // 2

	// max element
	auto max_e = max_element(iv.begin(), iv.end());
	cout << *max_e << endl; // 5

	// min
	cout << min(1, 3) << endl; // 1
	cout << min(2, 2) << endl; // 2

	// min element
	auto min_e = min_element(iv.begin(), iv.end());
	cout << *min_e << endl; // 1

	// minmax
	pair<int, int> min_max = minmax({5,2,3,1,4});
	min_max = minmax(1,5);
	cout << min_max.first << " " << min_max.second << endl; // 1 5

	// minmax_element
	pair<vector<int>::iterator, vector<int>::iterator>
		min_max_element = minmax_element(iv.begin(), iv.end());
	cout << "max= "<< *min_max_element.first <<
		" at position " << min_max_element.first - iv.begin() << endl;
	// max= 1 at position 0
	cout << "min= "<< *min_max_element.first <<
		" at position " << min_max_element.second - iv.begin() << endl;
	// min= 1 at position 4

	return 0;
}

Back to top

Partition

is_partitioned partition stable_partition partition_copy partition_point

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
using namespace std;

bool isOdd(int n){return (n % 2 == 1);}

int main(int argc, char const *argv[])
{
	vector<int> iv(8);
	iota(iv.begin(), iv.end(), 1);
	vector<int>::iterator bond;

	// partition
	bond = partition(iv.begin(), iv.end(), isOdd); // iv: 1 7 3 5 4 6 2 8

	cout << *bond << endl; // 4

	for (vector<int>::iterator i = iv.begin(); i != bond; ++i){
		cout << *i << " ";
	} cout << endl; // 1 7 3 5

	for (vector<int>::iterator i = bond; i != iv.end(); ++i){
		cout << *i << " ";
	} cout << endl; // 4 6 2 8


	// stable_partition
	iota(iv.begin(), iv.end(), 1); // iv: 1 2 3 4 5 6 7 8

	bond = stable_partition(iv.begin(), iv.end(), isOdd);
	// iv: 1 3 5 7 2 4 6 8

	cout << *bond << endl; // 2

	for (vector<int>::iterator i = iv.begin(); i != bond; ++i){
		cout << *i << " ";
	} cout << endl; // 1 3 5 7

	for (vector<int>::iterator i = bond; i != iv.end(); ++i){
		cout << *i << " ";
	} cout << endl; // 2 4 6 8


	// is_partitioned
	cout << boolalpha;
	// iv: 1 3 5 7 2 4 6 8
	cout << is_partitioned(iv.begin(), iv.end(), isOdd) << endl; // true

	iota(iv.begin(), iv.end(), 1);

	// iv: 1 2 3 4 5 6 7 8
	cout << is_partitioned(iv.begin(), iv.end(), isOdd) << endl; // false


	// partition_copy
	// iv: 1 2 3 4 5 6 7 8
	vector<int> even, odd;
	odd.resize(4); even.resize(4);

	partition_copy(iv.begin(), iv.end(), odd.begin(), even.begin(), isOdd);

	for (vector<int>::iterator i = odd.begin(); i != odd.end(); ++i){
		cout << *i << " ";
	} cout << endl; // 1 3 5 7

	for (vector<int>::iterator i = even.begin(); i != even.end(); ++i){
		cout << *i << " ";
	} cout << endl; // 2 4 6 8


	// partition_point
	partition(iv.begin(), iv.end(), isOdd); // iv: 1 7 3 5 4 6 2 8
	bond = partition_point(iv.begin(), iv.end(), isOdd);

	cout << *bond << endl; // 4

	return 0;
}

Back to top

Permutation

lexicographical_compare: Returns true if the range [first1,last1) compares lexicographically less than the range [first2,last2).

next_permutation: next lexicographically-ordered permutation. Return false when input is already the greatest lexicographic permutation.

prev_permutation: previous lexicographically-ordered permutation. Return false when input is already a ascending permutation.

THis code explain how to find next permutation(prev_permutation with same logic).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
template<class BidirIt> //BidirIt binary direction iterator
bool next_permutation(BidirIt first, BidirIt last) // [first, last)
{
    if (first == last) return false; //0 element
    BidirIt i = last;
    if (first == --i) return false; //one element

    while (true) {
        BidirIt i1, i2;
        i1 = i; // i1 is last element of ascending sequence
        if (*--i < *i1) { // i is prev of i1.
            i2 = last;
            while (*i > *--i2) // i ≤ i1 ≥ i2 // i2 will be last number bigger than i
                ;
            std::iter_swap(i, i2); // i2 should at i's position in the next permutation.
            std::reverse(i1, last); // make sure seq behind i1 become ascending.
            return true;
        }
        if (i == first) { // the whole sequence is descending.
            std::reverse(first, last);
            return false;
        }
    }
}

If you want go over all permutation, sort first.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <iostream>     // std::cout
#include <algorithm>    // std::next_permutation, std::sort
#include <string>
#include <vector>
using namespace std;

int main () {
	// next_permutation
	vector<int> myints = {1,2,3};
	sort(myints.begin(), myints.end()); // 1 2 3

	do {
	std::cout << myints[0] << ' ' << myints[1] << ' ' << myints[2] << '\n';
	} while ( next_permutation(myints.begin(), myints.end()) );

	std::cout << "After loop: " << myints[0] << ' ' << myints[1] << ' ' << myints[2] << '\n';

	// prev_permutation
	reverse(myints.begin(), myints.end()); // 3 2 1

	do {
	std::cout << myints[0] << ' ' << myints[1] << ' ' << myints[2] << '\n';
	} while ( prev_permutation(myints.begin(), myints.end()) );

	std::cout << "After loop: " << myints[0] << ' ' << myints[1] << ' ' << myints[2] << '\n';

	// lexicographical_compare
	string myStr = "abc"; // string is also work
	next_permutation(myStr.begin(), myStr.end());
	cout << myStr << endl; // acb

	string myStr2 = "cba";
	cout << boolalpha;
	cout << lexicographical_compare(myStr.begin(), myStr.end(), myStr2.begin(), myStr2.end()) << endl;
	// acb < cba
	// true

	// is_permutation
	cout << is_permutation(myStr.begin(), myStr.end(), myStr2.begin()) << endl;
	// true

	return 0;
}

Back to top

Remove

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

int main(int argc, char const *argv[])
{
	vector<int> iv = {10,20,30,30,20,10,10,20};

	//remove
	vector<int>::iterator newEnd = remove(iv.begin(), iv.end(), 20);
	//iv: 10 30 30 10 10 10 10 20
	//           newEnd: ^

	for (vector<int>::iterator i = iv.begin(); i != newEnd; ++i)
	{
		cout << *i << " ";
	}cout << endl; // res: 10 30 30 10 10

	vector<int> iv2 = {10,20,30,30,20,10,10,20};
	vector<int> iv3(5);

	// remove_copy
	remove_copy(iv2.begin(), iv2.end(), iv3.begin(), 20);
	// iv3: 10 30 30 10 10

	// remove_if
	vector<int> iv4 = {1,2,3,4,5,6,7,8,9};
	newEnd = remove_if(iv4.begin(), iv4.end(), [](int a){ return a % 2 == 0;});

	for (vector<int>::iterator i = iv4.begin(); i != newEnd; ++i)
	{
		cout << *i << " ";
	}cout << endl; // res: 1 3 5 7 9
	// iv4: 1 3 5 7 9 6 7 8 9

	// remove_copy_if
	vector<int> iv5 = {1,2,3,4,5,6,7,8,9};
	vector<int> iv6(5);
	remove_copy_if(iv4.begin(), iv4.end(), iv6.begin() , [](int a){ return a % 2 == 0;});
	// iv6: 1 3 5 7 9

	return 0;
}

Back to top

Replace

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

int main(int argc, char const *argv[])
{
	vector<int> iv = {10, 20, 30, 30, 20, 10, 10, 20};

	// replace
	replace(iv.begin(), iv.end(), 20, 99);
	// iv: 10 99 30 30 99 10 10 99

	// replace_copy
	vector<int> iv2(8);
	replace_copy(iv.begin(), iv.end(), iv2.begin(), 99, 1);
	// iv2: 10 99 30 30 99 10 10 99

	// replace_if
	replace_if(iv.begin(), iv.end(), [](int a){return a % 2 == 0;}, 0);
	// iv: 0 99 0 0 99 0 0 99

	// replace_copy_if
	vector<int> iv3(8);
	replace_copy_if(iv.begin(), iv.end(), iv3.begin(), [](int a){return a % 2 == 0;}, 1);
	// iv3: 1 99 1 1 99 1 1 99

	return 0;
}

Back to top

Reverse

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

int main(int argc, char const *argv[])
{
	vector<int> iv = {0,1,2,3,4,5,6,7};
	vector<int> iv2(8);

	// reverse
	reverse(iv.begin(), iv.end());
	// iv: 7 6 5 4 3 2 1 0

	// reverse_copy
	reverse_copy(iv.begin(), iv.end(), iv2.begin());
	// iv: 7 6 5 4 3 2 1 0
	// iv2: 0 1 2 3 4 5 6 7

	return 0;
}

Back to top

rotate

Here is how rotate achieve:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
template <class ForwardIterator>
  void rotate (ForwardIterator first, ForwardIterator middle,
               ForwardIterator last)
{
  ForwardIterator next = middle;
  while (first!=next)
  {
    swap (*first++,*next++);
    if (next==last) next=middle;
    else if (first==middle) middle=next;
  }
}

The idea is move a part to the end and adjust it

1
2
3
1 2 3 4 5 6 7 -> 4 5 6 1 2 3 7 -> 4 5 6 7 2 3 1 -> 4 5 6 7 1 3 2 -> 4 5 6 7 1 2 3

^     ^                ^     ^            ^   ^              ^ ^
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

int main(int argc, char const *argv[])
{
	vector<int> iv = {0,1,2,3,4,5,6,7,8,9};
	vector<int> iv2(10);

	rotate(iv.begin(), iv.begin()+3, iv.end());
	// iv: 3 4 5 6 7 8 9 0 1 2

	rotate_copy(iv.begin(), iv.begin()+3, iv.end(), iv2.begin());
	// iv: [3 4 5] 6 7 8 9 0 1 2
	// iv2: 6 7 8 9 0 1 2 [3 4 5]

	return 0;
}

Back to top

lower_bound upper_bound equal_range. These 3 method design like binary search. For example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
template <class ForwardIterator, class T>
  ForwardIterator lower_bound (ForwardIterator first, ForwardIterator last, const T& val)
{
  ForwardIterator it;
  iterator_traits<ForwardIterator>::difference_type count, step;
  count = distance(first,last);
  while (count>0)
  {
    it = first; step=count/2; advance (it,step);
    if (*it<val) {// or: if (comp(*it,val)), for version (2)
      first=++it;
      count-=step+1;
    }
    else count=step;
  }
  return first;
}

template <class ForwardIterator, class T>
  pair<ForwardIterator,ForwardIterator>
    equal_range (ForwardIterator first, ForwardIterator last, const T& val)
{
  ForwardIterator it = std::lower_bound (first,last,val);
  return std::make_pair ( it, std::upper_bound(it,last,val) );
}

lower_bound is more like a binary search

binary_search search one element and return a boolean.

find search one element and return the first one position.

search is searching a pattern and return the first position.

find_end is searching a pattern and return the last one (compare with search).

find_first_of find the first element that pattern have.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
#include <utility> // pair
#include <functional> // greater<int>
using namespace std;

int main(int argc, char const *argv[])
{
	vector<int> iv = {10,20,30,30,20,10,10,20};

	sort(iv.begin(), iv.end()); // 10 10 10 20 20 20 30 30

	// lower_bound & upper_bound
	vector<int>::iterator low, up;
	low = lower_bound(iv.begin(), iv.end(), 20);
	up = upper_bound(iv.begin(), iv.end(), 20);

	cout << "lower bound position: " << low - iv.begin() << endl;
	// lower bound position: 3
	cout << "upper bound position: " << up - iv.begin() << endl;
	// upper bound position: 6

	vector<int> test = {1,2,3,0,0,0};
	//                    low ^
	low = lower_bound(iv.begin(), iv.end(), 0, greater<int>());

	// equal_range
	pair<vector<int>::iterator, vector<int>::iterator> bounds;
	bounds = equal_range(iv.begin(), iv.end(), 20);

	cout << "bounds at positions " << (bounds.first - iv.begin());
  	cout << " and " << (bounds.second - iv.begin()) << endl;
  	// 10 10 10 20 20 20 30 30
  	//          ^        ^
  	// bounds at positions 3 and 6

  	// mismatch
  	vector<int> mis = {10,10,10,20,20,30,30,40};
	pair<vector<int>::iterator, vector<int>::iterator> myPair;
	myPair = mismatch(iv.begin(), iv.end(), mis.begin());
	//  iv: 10 10 10 20 20 20 30 30
	//              first: ^
	// mis: 10 10 10 20 20 30 30 40
	//             second: ^
	cout << "First mismacth is: " << *myPair.first << " ";
	cout << "and " << *myPair.second << endl;
	// First mismacth is: 20 and 30

	++myPair.first; ++myPair.second;
	myPair = mismatch(myPair.first, iv.end(), myPair.second);
	cout << "First mismacth is: " << *myPair.first << " ";
	cout << "and " << *myPair.second << endl;
	// First mismacth is: 30 and 40

  	// binary_search
  	cout << boolalpha;
  	cout << binary_search(iv.begin(), iv.end(), 20) << endl; // true;

  	// search
  	vector<int> searchV;
  	for (int i = 0; i < 10; ++i) {
  		searchV.push_back(i*10);
  	}

  	vector<int> patternV1 = {30,40,50};
  	vector<int> patternV2 = {30,50};

  	vector<int>::iterator it = search(searchV.begin(), searchV.end(), patternV1.begin(), patternV1.end());

  	// searchV: 0 10 20 30 40 50 60 70 80 90
  	//       pattern1 = 30 40 50
  	if(it != searchV.end())
  		cout << "Pattern is find and position is start from: " << it - searchV.begin() << endl;
  	else
  		cout << "Pattern not find." << endl;
  	// Pattern is find and position is start from: 3



  	it = search(searchV.begin(), searchV.end(), patternV2.begin(), patternV2.end());
	// searchV: 0 10 20 30 40 50 60 70 80 90
  	// pattern1 = 30 50
  	if(it != searchV.end())
  		cout << "Pattern is find and position is start from: " << it - searchV.begin() << endl;
  	else
  		cout << "Pattern not find." << endl;
	// Pattern not find.


  	// search_n
  	it = search_n(iv.begin(), iv.end(), 3, 20);
  	// iv: 10 10 10 20 20 20 30 30
  	//             {20 20 20}
	if(it != iv.end())
  		cout << "Pattern is find and position is start from: " << it - iv.begin() << endl;
  	else
  		cout << "Pattern not find." << endl;
	// Pattern is find and position is start from: 3

  	it = search_n(iv.begin(), iv.end(), 4, 10);
  	// iv: 10 10 10 20 20 20 30 30
  	// {10 10 10 10}
	if(it != iv.end())
  		cout << "Pattern is find and position is start from: " << it - iv.begin() << endl;
  	else
  		cout << "Pattern not find." << endl;
	// Pattern not find.


  	// find
	// searchV: 0 10 20 30 40 50 60 70 80 90
	//                     ^
  	it = find(searchV.begin(), searchV.end(), 40);
  	if(it != searchV.end())
  		cout << "Element is find in position: " << it - searchV.begin() << endl;
  	else
  		cout << "Element not find." << endl;
	// Element is find in position 4


  	// find_if
	// searchV: 0 10 20 30 40 50 60 70 80 90
	//                  ^
  	it = find_if(searchV.begin(), searchV.end(),[](int a){return a!=0 && a%3==0;});

  	if(it != searchV.end())
  		cout << "Element is find in position: " << it - searchV.begin() << endl;
  	else
  		cout << "Element not find." << endl;
	// Element is find in position 3

  	// find_if_not
  	// searchV: 0 10 20 30 40 50 60 70 80 90
	//                     ^
  	it = find_if_not(searchV.begin(), searchV.end(),[](int a){return a < 40;});
  	if(it != searchV.end())
  		cout << "Element is find in position: " << it - searchV.begin() << endl;
  	else
  		cout << "Element not find." << endl;
	// Element is find in position 4


  	// find_end
  	vector<int> findV = {1,2,3,4,5,1,2,3,4};
  	vector<int> pattern3 = {1,2,3};
  	// findV: 1 2 3 4 5 1 2 3 4
	//    	   pattern: 1 2 3
  	it = find_end(findV.begin(), findV.end(), pattern3.begin(), pattern3.end());
  	if(it != findV.end())
  		cout << "Element is find in position: " << it - findV.begin() << endl;
  	else
  		cout << "Element not find." << endl;
	// Element is find in position 5


  	// find_first_of
  	vector<int> pattern4 = {0,4};
  	// findV: 1 2 3 4 5 1 2 3 4
	//   pattern: 0 4
	//              ^
  	it = find_first_of(findV.begin(), findV.end(), pattern4.begin(), pattern4.end());
  	if(it != findV.end())
  		cout << "Element is find in position: " << it - findV.begin() << endl;
  	else
  		cout << "Element not find." << endl;
	// Element is find in position 3

	// adjacent_find
  	// iv: 10 10 10 20 20 20 30 30
  	// 	   ^
  	//              ^
  	it = adjacent_find(iv.begin(), iv.end());
  	cout << "The first adjacent number is " << *it << endl; // 10

  	it = adjacent_find(++++it, iv.end());
  	cout << "The second adjacent number is " << *it << endl; // 20

	return 0;
}

Back to top

Set

Container must be sorted first. Set is ordered in this code.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include <iostream>
#include <vector>
#include <algorithm>
#include <set>
using namespace std;

int main(int argc, char const *argv[])
{
	set<int> is1 = { 5,10,15,20,25};
	set<int> is2 = { 50,40,30,20,10};

	// set_union
	vector<int> iv_union(10);
	vector<int>::iterator it;
	it = set_union(is1.begin(), is1.end(), is2.begin(), is2.end(), iv_union.begin());
	iv_union.resize(it - iv_union.begin());
	// iv_union: 5 10 15 20 25 30 40 50

	// set_intersection
	vector<int> iv_intersection(10);
	it = set_intersection(is1.begin(), is1.end(), is2.begin(), is2.end(), iv_intersection.begin());
	iv_intersection.resize(it - iv_intersection.begin());
	// iv_intersection: 10 20

	// set_difference
	vector<int> iv_difference(10);
	it = set_difference(is1.begin(), is1.end(), is2.begin(), is2.end(), iv_difference.begin());
	iv_difference.resize(it - iv_difference.begin());
	// iv_difference: 5 15 25 // difference only in first container

	// set_symmetric_difference
	vector<int> iv_symmetric_difference(10);
	it = set_symmetric_difference(is1.begin(), is1.end(), is2.begin(), is2.end(), iv_symmetric_difference.begin());
	iv_symmetric_difference.resize(it - iv_symmetric_difference.begin());
	// iv_symmetric_difference: 5 15 25 30 40 50 // difference only in both containers

	return 0;
}

Back to top

Shuffle

  1. The only difference is that randomshuffle uses _rand() function to randomize the items, while the shuffle uses urng which is a better random generator, though with the particular overload of random_shuffle, we can get the same behavior (as with the shuffle).

  2. shuffle is an improvement over random_shuffle, and we should prefer using the former for better results. But shuffle supported from C++11.

reference

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <iostream>
#include <vector>
#include <algorithm> // random_shuffle shuffle
#include <numeric> // iota
#include <ctime> // std::time
#include <cstdlib> // rand, srand
#include <random>       // std::default_random_engine
#include <chrono>       // std::chrono::system_clock
using namespace std;

int myrandom(int i) { return rand()%i; }
int main(int argc, char const *argv[])
{
	srand(unsigned(time(0)));
	vector<int> iv(10);
	iota(iv.begin(), iv.end(), 0); // iv: 0 1 2 3 4 5 6 7 8 9

	random_shuffle(iv.begin(), iv.end()); // 6 0 3 5 7 8 4 1 2 9
	random_shuffle(iv.begin(), iv.end(), myrandom); // It is random, since srand set by time.

	iota(iv.begin(), iv.end(), 0); // iv: 0 1 2 3 4 5 6 7 8 9
	unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
	shuffle(iv.begin(), iv.end(), std::default_random_engine(seed)); // It is random

	return 0;
}

Back to top

Sort

sort() in c++ using intro sort which is combine quicksort and heap sort.

stable_sort() using merge sort. When space is enough, the complexity is O(nlogn). Otherwise, it is O(nlognlogn) since many swapping occur in algorithm.

partial_sort using heapsort.

nth_element: Rearranges the elements in the range [first,last), in such a way that the element at the nth position is the element that would be in that position in a sorted sequence.

nth_element is quick selection. Find the nth element and put it the exact place. On the right part is smaller than nth element and bigger on the left without specific sequence.

Something different in java. You can see: Here

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#include <iostream>
#include <algorithm>
#include <functional>
#include <vector>
#include <utility> //pair
using namespace std;

struct less{
	bool operator() (pair<int,int> i, pair<int,int> j){return( i.first < j.first);}
} less_pair;

int main(int argc, char const *argv[])
{
	int myints[] = {32,71,12,45,26,80,53,33};
	vector<int> iv (myints, myints+8);

	// is_sort
	cout << boolalpha;
	cout << is_sorted(iv.begin(), iv.end()) << endl;

	// sort
	sort(myints, myints+8); // 12 26 32 33 45 53 71 80
	cout << is_sorted(myints, myints+8) << endl; // true
	sort(iv.begin(), iv.begin() + 4, greater<int>()); // (71 45 32 12) 26 80 53 33

	// is_sorted_until
	auto iter1 = is_sorted_until(myints, myints+8);
	auto iter2 = is_sorted_until(iv.begin(), iv.end(), greater<int>());
	cout << *iter1 << endl; // ???
	cout << *iter2 << endl; // 26

	// partial_sort
	vector<int> iv2 = {32,71,12,45,26,80,53,33};

	partial_sort(iv2.begin(), iv2.begin() + 4, iv2.end());
    // (12 26 32 33) 71 80 53 45
	partial_sort(iv2.begin(), iv2.begin() + 4, iv2.end(), greater<int>());
    // (80 71 53 45) 12 26 32 33

	// partial_sort_copy
	vector<int> res_copy(6);

	partial_sort_copy(iv2.begin(), iv2.end(), res_copy.begin(), res_copy.end());

	// iv2 --> 12 26 32 33 71 80 53 45
	// res_copy --> 12 26 32 33 45 53

	// stable_sort
	pair<int, int> p1(4, 1); pair<int, int> p2(2, 1); pair<int, int> p3(3, 1);
	pair<int, int> p4(2, 2); pair<int, int> p5(1, 1); pair<int, int> p6(2, 3);

	vector<pair<int, int>> iv3 = {p1, p2, p3, p4, p5, p6};

	stable_sort(iv3.begin(), iv3.end(), less_pair);
    //(1 1) (2 1) (2 2) (2 3) (3 1) (4 1)

	// nth_element
	vector<int> iv4 = {32,71,12,45,26,80,53,33};
	nth_element(iv4.begin(), iv4.begin()+4 , iv4.end());
	// 26 12 32 33 45 53 71 80
	//        n is ^
	return 0;
}

Back to top

Swap

iter_swap: Swap the value of two iterators.

swap: Only use for swap two variable

swap_ranges: Exchanges the values of each of the elements in the range [first1,last1) with those of their respective elements in the range beginning at first2.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

int main(int argc, char const *argv[])
{
	int a = 1, b = 2;
	swap(a, b); // b = 2, a = 1

	vector<int> iv = {1,2,3,4,5,6};

	int myints[] = {10,20,30,40,50,60};

	iter_swap(iv.begin(), iv.begin()+3); // 4 2 3 1 5 6
	iter_swap(myints, myints + 3); // 40 20 30 10 50 60

	iter_swap(iv.begin(), myints);
	// iv: 40 2 3 1 5 6
	// myints: 4 20 30 10 50 60

	// iv: 40 [2 3 1 5] 6
	// myints: [4 20 30 10] 50 60
	std::swap_ranges(iv.begin()+1, iv.end()-1, myints);
	// iv: 40 [4 20 30 10] 6
	// myints: [2 3 1 5] 50 60
}

Back to top

Test range

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;

int main(int argc, char const *argv[])
{
	cout << boolalpha;
	// all_of
	vector<int> iv = {1,2,3,4,5,6};
	cout << all_of(iv.begin(), iv.end(), [](int a){return a<10;}) << endl;
	//true

	// any_of
	cout << any_of(iv.begin(), iv.end(), [](int a){return a>10;}) << endl;
	// false

	// none_of
	cout << none_of(iv.begin(), iv.end(), [](int a){return a>10;}) << endl;
	// true

	// equal
	vector<int> iv2 = {1,2,3,4,5,6};
	vector<int> iv3 = {1,2,3,4,5};

	cout << equal(iv.begin(), iv.end(), iv2.begin()) << endl;
	// true
	cout << equal(iv.begin(), iv.end(), iv3.begin()) << endl;
	// false

	// includes
	cout << includes(iv2.begin(), iv2.end(), iv3.begin(), iv3.end()) << endl;
	// true

	return 0;
}

Back to top

Unique

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main(int argc, char const *argv[])
{
	vector<int> iv1 = {10,20,20,20,30,30,20,20,10};

	vector<int>::iterator it;

	// it point to the new end.
	it = unique(iv1.begin(), iv1.end());

	for (vector<int>::iterator i = iv1.begin(); i != it; ++i)
	{
		cout << *i << " ";
	}
	cout << endl;
	// 10 20 30 20 10

	vector<int> iv2 = {10,20,20,20,30,30,20,20,10};
	vector<int> iv3(5);

	it = unique_copy(iv2.begin(), iv2.end(), iv3.begin());
	for (vector<int>::iterator i = iv3.begin(); i != it; ++i)
	{
		cout << *i << " ";
	}
	cout << endl;
	// 10 20 30 20 10
	return 0;
}

Back to top