STL 제네릭 알고리즘 정리

accumulate()
기본적으로, 컨테이너의 요소들을 세 번째 인수로 지정한 초기값에 모두 더합니다. 기본 덧셈을 오버라이딩하기 위해 이항 연산을 넘길 수 있습니다.

#include <numeric>

iresult = accumulate(ia, ia + 9, 0);
iresult = accumulate(ilist.begin(), ilist.end(), 0, plus<int>());

adjacent_difference()
기본적으로 주어진 열 내에서 인접하는 각 요소의 차이를 값으로 하는 새로운 열을 생성합니다. {0, 1, 1, 2, 3, 5, 8}이 주어진다면 그 결과는 {0, 1, 0, 1, 1, 2, 3}이 됩니다. 기본 뺄셈을 오버라이딩하는 이항 연산을 넘길 수 있습니다. 예를 들면, times<int>는 {0, 0, 1, 2, 6, 15, 40}이라는 결과를 도출합니다. 세 번째 인수는 결과가 복사될 컨테이너를 가리키는 반복자입니다.

#include <numeric>

adjacent_difference(ilist.begin(), ilist.end(), iresult.begin());
adjacent_difference(ilist.begin(), ilist.end(), iresult.begin(), times<int>());

adjacent_find()
기본적으로 중복된 요소가 인접된 최초의 곳을 찾습니다. 기본 상등 연산자(==)를 오버라이딩하기 위해 이항 연산을 넘길 수 있습니다. 찾은 요소를 가리키는 반복자를 반환합니다.

#include <algorithm>
class TwiceOver {
public:
  bool operator() (int val1, int val2)
    { return val1 == val2 / 2 ? true : false; }
}

piter = adjacent_find(ia, ia + 8);
iter = adjacent_find(vec.begin(), vec.end(), TwiceOver());

binary_search()
컨테이너가 보다 작은가의 비교 연산자(<)로 정렬되어 있다고 가정합니다. 컨테이너가 다른 관계로 정렬되어 있다면 그에 대한 이항 연산자를 넘겨야 합니다. 알고리즘은 true나 false를 반환합니다.

#include <algorithm>
found_it = binary_search(ilist.begin(), ilist.end(), value);
found_it = binary_search(vec.begin(), vec.end(), value, greator<int>());

copy()
한 컨테이너의 요소들을 다른 컨테이너로 복사합니다.

#include <algorithm>
ostream_iterator<int> ofile(cout, " ");
copy(vec.begin(), vec.end(), ofile);

vector<string> target(svec.size());
copy(svec.begin(), svec.end(), target.begin());

copy_backward()
copy()와 동일하게 동작하시만, 요소들을 반대의 순서로 복사합니다.

#include <algorithm>
copy_backward(svec.begin(), svec.end(), target.begin());

count()
컨테이너 내에서 value와 같은 요소의 개수를 반환합니다.

#include <algorithm>
cout << value << " occurs " << count(svec.begin(), svec.end(), value) 
      << " times in string vector.\n";

count_if()
연산의 결과가 true로 계산되는 요소의 개수를 반환합니다.

#include <algorithm>
class Even {
public:
  bool operator()(int val) { return !(val % 2); }
}

ires = count_if(ia, ia + 8, bind2nd(less<int>(), 10));
ires = count_if(ilist.begin(), ilist.end(), Even());

equal()
두 열이 서로 같다면 true를 반환합니다. 이때 첫 컨테이너를 기준으로 하기 때문에 첫 컨테이너에 있는 요소의 개수만큼 비교됩니다. 기본적으로, 상등 연산자(==)가 사용되고, 함수 객체나 함수의 포인터를 지정할 수도 있습니다.

#include <algorithm>
class EqualAndOdd {
public:
  bool operator()(int v1, int v2)
    { return ((v1 == v2) && (v1 % 2)); }
}

int ia1[] = {1, 1, 2, 3, 5, 8, 13};
int ia2[] = {1, 1, 2, 3, 5, 8, 13, 21, 34};
res = equal(ia1, ia1 + 7, ia2); /* true */ 
res = equal(ia1, ia1 + 7, ia2, equalAndOdd()); /* false */

fill()
컨테이너 내에 있는 각 요소들에 대해 value를 대입합니다.

#include <algorithm>
fill(ivec.begin(), ivec.end(), value);

fill_n()
컨테이너 내에 있는 각 요소들에 대해 value를 count의 개수만큼 대입합니다.

#include <algorithm>
fill_n(ia, count, value);
fill_n(svec.begin(), count, string_value);

find()
컨테이너 내의 각 요소들을 value와 같은지 비교합니다. 같은 요소가 있다면 비교를 중단하고, 그 요소의 반복자를 반환합니다. 같은 요소가 없으면 container.end()를 반환합니다.

#include <algorithm>
piter = find(ia, ia + 8, value);
iter = find(svec.begin(), svec.end(), "rosebud");

find_end()
이 알고리즘은 두 쌍의 반복자를 매기변수로 받습니다. 첫 쌍은 검색될 컨테이너를 나타내고, 두 번째의 쌍은 검색할 열을 나타냅니다. 첫 컨테이너 내의 요소들에서 상등 연산자(==)나 지정된 이항 연산을 사용해서 마지막으로 일치되는 열을 찾습니다. 일치되면 일치된 열의 첫 요소를 가리키는 반복자를 반환합니다. 일치되는 요소가 없으면 첫 컨테이너의 끝을 표시하는 반복자를 반환합니다. 예를 들어 Mississippi라는 열이 주어졌을 때 두 번째 열이 ss라면 find_end()는 두 번째 ss의 첫 글자인 s를 가리키는 반복자를 반환합니다.

#include <algorithm>
int ia[17] = {7, 3, 3, 7, 6, 5, 8, 7, 2, 1, 3, 7, 6, 3, 8, 4, 3};
int seq[3] = {3, 7, 6};

/* found_it은 ia[10]을 가리키게 됩니다. */ 
found_it = find_end(ia, ia + 17, seq, seq + 3);

find_first_of()
find_first_of()는 두 쌍의 반복자를 매개변수로 받습니다. 첫 쌍은 검색될 요소들을 표시하고, 두 번째 쌍은 검색할 요소들의 모음을 표시합니다. 예를 들어, synesthesia라는 문자열에서 첫 모음을 찾으려면 두 번째 열을 aeiou로 정의합니다. find_first_of()는 모음이 처음으로 나타나는 요소의 반복자를 반환합니다. 이 경우는 최초의 e가 됩니다. 일치되는 것이 없으면 첫 열의 마지막을 가리키는 반복자를 반환합니다. 다섯 번째 매개변수로 기본 상등 연산자를 오버라이딩 할 수 있는 이항 연산을 추가할 수도 있습니다.

#include <algorithm>
string s_array[] = {"Ee", "eE", "ee", "Oo", "oo", "ee"};
string to_find[] = {"oo", "gg", "ee"};

/* &s_array[2]에 있는 최초의 "ee"를 반환합니다. */ 
found_it = find_first_of(s_array, s_array + 6, to_find, to_find + 3);

find_if()
컨테이너 내의 요소들을 지정된 이항 연산으로 비교합니다. 일치되는 요소가 발견되면 검색이 중단됩니다. find_if()는 일치된 요소의 반복자를 반환하고, 일치되는 요소가 없으면 container.end()를 반환합니다.

#include <algorithm>
find_if(vec.begin(), vec.end(), LessThanVal(ival));

for_each()
for_each()는 세 번째 매개변수로 받은 연산을 각 요소들에 적용합니다. 이 연산은 요소들을 수정할 수는 없습니다(transform()을 쓰면 수정할 수 있습니다). 연산이 값을 반환해도 그 값은 무시됩니다.

#include <algorithm>
template<typename Type>
void print_elements(Type elem) { cout << elem << " "; };

for_each(ivec.begin(), ivec.end(), print_elements);

generate()
generate()는 지정된 생성자를 적용시켜 열을 채우게 됩니다.

#include <algorithm>
class GenByTwo {
   void operator() {
      static int seed = -1; return seed += 2;
   }
};
list<int> ilist<10>;

/* ilist에 채워질 값: 1 3 5 7 9 11 13 15 17 19 */ 
generate(ilist.begin(), ilist.end(), GenByTwo());

generate_n()
generate_n()은 지정된 생성자를 n부터 호출해 열을 채우게 됩니다.

#include <algorithm>
class gen_by_two {
public:
   gen_by_two(int seed = 0) : _seed(seed) {}
   int operator()() { return _seed += 2; }
private:
   int _seed;
};
vector<int> ivec(10);

/* ivec에 채워질 값: 102 104 106 108 110 112 114 116 118 120 */ 
generate_n(ivec.begin(), ivec.size(), gen_by_two(100));

includes()
두 번째 열의 모든 요소가 첫 번째 열에 포함되어 있다면 includes()는 true를 반환하고, 그렇지 않으면 false를 반환합니다. 양쪽 열 모두 기본 비교 연산자(<)나 지정된 연산으로 정렬하여 있어야 합니다. 지정된 연산은 다섯 번째 매개변수로 넘겨집니다.

#include <algorithm>
int ia1[] = {13, 1, 21, 2, 0, 34, 5, 1, 8, 3, 21, 34};
int ia2[] = {21, 2, 8, 3, 5, 1};

/* includes에는 정렬된 컨테이너를 넘겨야 합니다. */ 
sort(ia1, ia1 + 12); sort(ia2, ia2 + 6);
res = includes(ia1, ia1 + 12, ia2, ia2 + 6); // true

inner_product()
inner_product()는 두 열의 내적(inner product)값을 사용자가 지정한 초기값에 차례로 더합니다. 예를 들어, 두 열 {2,3,5,8}과 {1,2,3,4}가 주어졌다면 결과값은 (2*1)+(3*2)+(5*3)+(8*4)가 됩니다. 만약 초기값으로 0을 주었다면 결과는 55가 됩니다. 두 번째 형태는 기본 덧셈과 곱셈 연산을 오버라이딩할 수 있습니다. 예를 들어, 같은 열에 대해 뺄셈과 덧셈을 지정하면 결과는 (2+1)-(3+2)-(5+3)-(8+4)가 됩니다. 초기값으로 0을 주었으면 결과는 -28이 됩니다.

#include <numeric>
int ia[] = {2, 3, 5, 8};
int ia2[] = {1, 2, 3, 4};
int res = inner_product(ia, ia + 4, ia2, 0);

vector<int> vec(ia, ia + 4);
vector<int> vec2(ia2, ia2 + 4);

res = inner_product(vec.begin(), vec.end(), vec2.begin(), 0, minus<int>(), plus<int>());

inplace_merge()
inplace_merge()는 first, middle, last라는 세 개의 반복자를 매개변수로 받습니다. 두 입력열은 [first, middle]과 [middle, last]로 표시죕니다(middle은 첫 열의 마지막 요소에서 하나가 더 지납니다). 이 열들은 연속적이어야 합니다. 결과 열은 first에서 시작해 두 범위를 모두 덮어씁니다. 선택적인 네 번째 매개변수에 기본 연산자가 아닌 다른 정렬 알고리즘을 지정할 수 있습니다.

#include <algorithm>
int ia[20] = {29, 23, 20, 17, 15, 26, 51, 12, 35, 40, 74, 16, 54, 21, 44, 62, 10, 41, 65, 71};
int *middle = ia + 10, *last = ia + 20;

/* 12 15 17 20 23 26 29 35 40 51 10 16 21 41 44 54 62 65 71 74 */ 
sort(ia, middle); sort(middle, last);

/* 10 12 15 16 17 20 21 23 26 29 35 40 41 44 51 54 62 65 71 74 */ 
inplace_merge(ia, middle, last);

iter_swap()
두 반복자가 가리키는 요소들 안에 저장된 값들을 바꿉니다.

#include <algorithm>
typedef list<int>::iterator iterator;
iterator it1 = ilist.begin(), it2 = ilist.begin() + 4;
iter_swap(it1, it2);
lexicographical_compare()

기본적으로, 보다 작은가의 비교 연산자(<)가 적용됩니다. 선택적인 다섯 번째 매개변수로 다른 배치 연산을 제공할 수도 있습니다. 첫째 열이 둘째 열보다 작거나 같다면 true가 반환됩니다.

#include <algorithm>
class size_compare {
public:
   bool operator()(const string& a, const string& b) {
      return a.length() <= b.length();
   }
};
string sa1[] = {"Piglet", "Pooh", "Tigger"};
string sa2[] = {"Piglet", "Pooch", "Eeyore"};

/* 'c'가 'h' 보다 작기 때문에 false */ 
res = lexicographical_compare(sa1, sa1 + 3, sa2, sa2 + 3);

list<string> ilist1(sa1, sa1 + 3);
list<string> ilist2(sa2, sa2 + 3);

/* Pooh < Pooch이므로 true */ 
res = lexicographical_compare(ilist1.begin(), ilist1.end(), ilist2.begin(), ilist2.end(), size_compare());

max(), min()

두 요소 중 더 큰것(혹은 더 작은 것)을 반환합니다. 세 번째 매개변수에 다른 비교 연산을 제공할 수도 있습니다.

max_element(), min_element()
열 내에서 가장 큰 값(혹은 가장 작은 값)을 가리키는 반복자를 반환합니다. 세 번째 매개변수에 다른 비교 연산을 제공할 수도 있습니다.

#include <algorithm>
int mval = max(max(max(max(ivec[4], ivec[3]), ivec[2]), ivec[1]), ivec[0]);
mval = min(min(min(min(min(ivec[4], ivec[3]), ivec[2]), ivec[1]), ivec[0]);

vector<int>::const_iterator iter;
iter = max_element(ivec.begin(), ivec.end());
iter = min_element(ivec.begin(), ivec.end());

merge()
두 개의 정렬된 열을 다섯 번째 반복자가 가리키는 하나의 정렬된 열로 합칩니다. 선택적으로, 여섯 번째 매개변수에 기본 비교 연산자가 아닌 다른 정렬 연산자를 줄 수도 있습니다.

#include <algorithm>
int ia[12] = {29, 23, 20, 22, 17, 15, 26, 51, 19, 12, 35, 40};
int ia2[12] = {74, 16, 39, 54, 21, 44, 62, 10, 27, 41, 65, 71};

vector<int> vec1(ia, ia + 12), vec2(ia2, ia2 + 12);
vector<int> vec_result(vec1.size() + vec2.size());

sort(vec1.begin(), vec1.end(), greater<int>());
sort(vec2.begin(), vec2.end(), greater<int>());

merge(vec1.begin(), vec1.end(), vec2.begin(), vec2.end(), vec_result.begin(), greater<int>());

nth_element()

nth_element()는 nth 요소보다 작은 모든 요소들이 앞에 나타나고, 그보다 큰 모든 요소들이 뒤에 나오도록 열을 재배치합니다. 예를 들어, 다음의 열이 주어졌다면

 

int ia[] = {29, 23, 20, 22, 17, 15, 26, 51, 19, 12, 35, 40};

nth로 ia + 6(이 값은 26)을 표시하여 nth_element()를 호출해보겠습니다.

 

nth_element(ia, ia + 6, &ia?12);

이 결과는 26보다 작은 7의 요소는 왼쪽에 위치되고, 26보다 큰 4개의 요소는 26의 오른쪽에 위치됩니다.

 

{23, 20, 22, 17, 15, 19, 12, 26, 51, 35, 40, 29}

nth 요소의 양쪽에 있는 요소들은 특정한 순서로 되어 있음을 보증할 수 없습니다. 선택적으로, 네 번째 매개변수에 기본 비교 연산자를 대신할 수 있는 비교를 지정할 수 있습니다.

partial_sort(), partial_sort_copy()

partial_sort()는 first, middle, last의 세 매개변수를 받습니다. 선택적으로 다른 배치 연산을 제공하는 네 번째 매개변수를 받을 수 잇습니다. 반복자 first와 middle은 컨테이너의 정렬된 요소들을 배치시킬 슬롯의 범위를 표시합니다(middle은 유효한 슬롯의 마지막보다 1이 큽니다). middle에서 last까지 저장된 요소들은 정렬되지 않았습니다. 예를 들어, 다음 배열이 주어졌다면

 

int ia[] = {29, 23, 20, 22, 17, 15, 26, 51, 19, 12, 35, 40};

middle로 여섯 번째 요소를 표시해서 partial_sort()를 호출하겠습니다.

 

partial_sort(ia, ia + 5, ia + 12);

이렇게 하면 가장 작은 다섯 요소들이 정렬됩니다.

 

{12, 15, 17, 19, 20, 29, 23, 22, 26, 51, 35, 40}

middle에서 last -1까지의 요소들은 특정한 순서로 배치되지 않습니다.

partial_sum()
기본적으로, 각 요소가 이전의 모든 요소들부터 그 위치까지를 합으로 하는 새로운 열을 만듭니다. 예를 들어, {0, 1, 1, 2, 3, 5, 8}의 열이 주어졌다면 새로운 열은 {0, 1, 2, 4, 7, 12, 20}이 됩니다. 네 번째 요소를 예로 들면, 이전의 세 값인 (0, 1, 1)의 합과 자신인 (2)를 더합니다. 선택적으로, 네 번째 매개변수에 적용될 연산을 지정할 수도 있습니다.

#include <numeric>
int ires[7], ia[7] = {1, 3, 4, 5, 7, 8, 9};
vector<int> vres(7), vec(ia, ia + 7);

/* partial_sum(): 1 4 8 13 20 28 37 */ 
partial_sum(ia, ia + 7, ires);

/* times<int>()를 사용한 partial_sum: 1 3 12 60 420 3360 30240 */ 
partial_sum(vec.begin(), vec.end(), vres.begin(), times<int>());

partition(), stable_partition()
partition()은 단항 연산의 결과인 true/false에 따라 요소들을 재배치시킵니다. true로 계산된 모든 요소들은 false로 계산된 요소들의 앞에 위치됩니다. 예를 들어, {0, 1, 2, 3, 4, 5, 6}의 열이 주어지고 짝수인지를 검사한다면 true와 false는 각각 {0, 2, 4, 6}과 {1, 3, 5}가 됩니다. 모든 짝수 요소들은 홀수 요소들의 앞에 위치되지만, 재배치된 열에서 각각의 상대적인 위치가 유지되는 것은 보증할 수 없습니다. stable_partition()은 상대적인 위치까지 유지시키는 것을 보증합니다.

#include <algorithm>
class even_elem {
public:
   bool operator()(int elem)
      { return elem % 2 ? false : true; }
};

int ia[] = {29, 23, 20, 22, 17, 15, 26, 51, 19, 12, 35, 40};
vector<int> vec(ia, ia + 12);

/* 요소가 짝수인지에 따라 재배치: 40 12 20 22 26 15 17 51 19 23 35 29 */ 
stable_partition(vec.begin(), vec.end(), even_elem());

random_shuffle()
기본적으로, random_shuffle()은 항들이 자신의 알고리즘에 따라 무작위적으로 배치합니다. 선택적으로, 세 번째 매개변수에 난수를 생성하는 연산을 넘길 수도 있습니다. 이 연산은 [0, 1] 사이에서 double 타입의 값을 반환해야 합니다.

#include <algorithm>
random_shuffle(ivec.begin(), ivec.end());

remove(), remove_copy()
remove()는 열 내에서 value와 같은 모든 요소들은 분리시켜 냅니다. 일치된 요소들을 실제로 지우지는 않습니다(컨테이너 크기는 그대로 유지됩니다). 다만, 일치되지 않은 요소들은 차례로 다음의 빈 슬롯에 대입뇝니다. 반환된 반복자는 새로운 요소들의 범위보다 1이 큰 곳을 가리킵니다. 예를 들어, {0, 1, 0, 2, 0, 3, 0, 4}의 열을 가정하겠습니다. 여기에서 모든 0 값을 제거한다고 하면 결과는 {1, 2, 3, 4, 0, 3, 0, 4}가 됩니다. 1은 첫째 슬롯에 복사되고, 2는 둘째 슬롯에, 3은 셋째 슬롯에, 4는 넷째 슬롯에 각각 복사됩니다. 다섯째 슬롯에 있는 0은 남은 것을 나타냅니다. 반환됩 반복자가 바로 여기를 가리킵니다. 일반적으로, 이 반복자는 erase()에 넘겨집니다(기본 배열은 크기가 쉽게 변경될 수 없기 때문에 remove() 알고리즘이 적합하지 않습니다. 이런 이유로, 배열에서는 remove_copy()가 더 적합한 알고리즙입니다).

#incldue <algorithm>

int ia[] = {0, 1, 0, 2, 0, 3, 0, 4, 0, 5};
vector<int> vec(ia, ia + 10);

/* erase()의 적용 없이 remove()한 후의 벡터: 1 2 3 4 5 3 0 4 0 5 */ 
vec_iter = remove(vec.begin(), vec.end(), 0);

/* erase() 후의 벡터: 1 2 3 4 5 */ 
vec.erase(vec_iter, vec.end());

int ia2[5];
/* ia2: 1 2 3 4 5 */ 
remove_copy(ia, ia + 10, ia2, 0);

remove_if(), remove_copy_if()
remove_if()는 주어진 연산 결과가 true인 모든 요소들을 제거합니다. 그렇지 않으면 remove_if()와 remove_copy_if()는 각각 remove()와 remove_copy()와 동일하게 동작합니다.

#include <algorithm>
class EvenValue {
public:
   bool operator()(int value) {
      return value % 2 ? false : true; 
   }
};

int ia[] = {0, 1, 1, 2, 3, 5, 8, 13, 21, 34};
vector<int> vec(ia, ia + 10);

iter = remove_if(vec.begin(), vec.end(), bind2nd(less<int>(), 10));
vec.erase(iter, vec.end());  /*/ 열은 이제 13 21 34가 됨 */

int ia2[10];
remove_copy_if(ia, ia + 10, ia2, EvenValue());

replace(), replace_copy()
replace()는 열 내에 있는 모든 old_value를 new_value로 대체합니다.

#include <algorithm>
string oldval("Mr. Winnie the Pooh");
string newval("Pooh");
string sa[] = {"Christopher Robin", "Mr. Winnie the Pooh", "Piglet", "Tigger", "Eeyore"};

vector<string> vec(sa, sa + 5);

/* Christopher Robin Pooh Piglet Tigger Eeyore */ 
replace(vec.begin(), vec.end(), oldval, newval);

vector<string> vec2;

/* Christopher Robin Mr. Winnie the Pooh Piglet Tigger Eeyore */ 
replace_copy(vec.begin(), vec.end(), inserter(vec2, vec2.begin()), newval, oldval);

replace_if(), replace_copy_if()
replace_if()는 열 내에서 비교 연산 결과가 true인 모든 요소들을 new_value로 대체합니다.

#include <algorithm>
int new_value = 0;
int ia[] = {0, 1, 1, 2, 3, 5, 8, 13, 21, 34};
vector<int> vec(ia, ia + 10);

/* 결과 : 0 0 0 0 0 0 0 13 21 34 */ 
replace_if(vec.begin(), vec.end(), bind2nd(less<int>(), 10), new_value);

reverse(), reverse_copy()
컨테이너 내에 있는 요소들의 순서를 반대로 합니다.

#include <algorithm>
list<string> slist_copy(slist.size());

reverse(slist.begin(), slist.end());
reverse_copy(slist.begin(), slist.end(), slist_copy.begin());

rotate(), rotate_copy()

rotate()는 first, middle, last 세 가지 반복자를 매개변수로 받습니다. first와 middle – 1로 표시되는 범위와 middle과 last – 1로 표시되는 범위를 서로 바꿉니다. 예를 들어, 다음과 같은 C 스타일의 문자열이 주어졌다고 가정하겠습니다.

 

char ch[] = “boohiss!!”;

이를 hissboo!!로 변경하려면 다음과 같이 rotate()를 호출합니다.

 

rotate(ch, ch + 3, ch + 7);

다음은 다른 예제입니다.

 

#incldue <algorithm> int ia[] = {1, 3, 5, 7, 9, 0, 2, 4, 6, 8, 10}; vector<int> vec(ia, ia + 11), vec2(11);

첫 번째 호출에서는 0으로 시작하는 마지막 여섯 개의 요소와 1로 시작하는 처음 다섯 개의 요소를 바꿉니다.

 

// 결과: 0 2 4 6 8 10 1 3 5 7 9 rotate(ia, ia + 5, ia + 11);

두 번째 호출에서는 8로 시작하는 마지막 두 개의 요소와 1로 시작하는 처음 9개의 요소를 바꿉니다.

 

// 결과: 8 10 1 3 5 7 9 0 2 4 6 rotate_copy(vec.begin(), vec.end – 2, vec.end, vec2.begin());search()
두 개의 열이 주어졌을 때 searh()는 첫 열에서 둘째 열이 나타나는 처음 위치를 가리키는 반복자를 반환합니다. 만약 일치되는 열이 없으면 첫 열의 마지막이 반환됩니다. 예를 들어, Mississippi 내에서 iss가 두 번 나타나는데, search()는 처음의 iss를 가리키는 반복자를 반환합니다. 선택적인 다섯 번째 매개변수로 기본 상등 연산자(==)를 오버라이딩할 수 있습니다.

#include <algorithm>

char str[25] = "a fine and private place";
char substr[4] = "ate";
int* piter = search(str, str + 25, substr, substr + 4);

search_n()
search_n()은 열 내에서 value가 n만큼 나타나는 곳을 찾습니다. 다음의 예제에서는 str에서 o가 연속적으로 두 번 나오는 곳을 찾습니다. 그래서 moose의 첫 o를 나타내는 반복자를 반환합니다. 일치되지 않으면 첫 열의 마지막을 가리키는 반복자를 반환합니다. 선택적인 다섯 번째 매개변수로 기본 상등 연산자를 오버라이딩할 수 있습니다.

#include <algorithm>
const char oh = 'o';

char str[26] = "oh my a mouse ate a moose";
char* found_str = search_n(str, str + 26, 2, oh);

set_difference()
set_difference()는 첫째 열에는 존재하고, 둘째 열에는 존재하지 않는 요소들로 이루어진 정렬된 열을 생성합니다. 예를 들어, {0, 1, 2, 3}과 {0, 2, 4, 6}이 주어진다면 연산의 결과는 {1, 3}이 됩니다. 모든 set 알고리즘(다음의 세 개의 알고리즘을 포함)은 다섯 개의 반복자를 매개변수로 받습니다. 첫째 열을 나타내는 두 개의 반복자와 둘째 열을 나타내는 두 개의 반복자 그리고 다섯번째 반복자는 요소들이 복사될 컨테이너를 가리킵니다. 알고리즘은 열들이 보다 작은가의 비교 연산자로 정렬되어 있다고 가정합니다. 여섯 번째의 선택적인 배개변수에는 다른 정렬 알고리즘을 넘길 수 있습니다.

set_intersection()

set_intersection()은 양쪽 열 모두 존재하는 요소들의 정렬된 열을 생성합니다. 예를 들어, {0, 1, 2, 3}과 {0, 2, 4, 6}이 주어진다면 결과는 {0, 2}가 됩니다.

set_symmetric_difference()

set_symmetric_difference()는 첫째 열에는 존재하지만, 둘째 열에는 존재하지 않는 요소들과 둘째 열에는 존재하지만, 첫째 열에는 존재하지 않는 요소들로 이루어진 정렬된 열을 생성합니다. 예를 들어, {0, 1, 2, 3}과 {0, 2, 4, 6}이 주어진다면 결과는 {1, 3, 4, 6}이 됩니다.

set_union()
set_union()은 두 개의 열 내에 있는 요소들이 모두 포함된 정렬된 열을 생성합니다. 예를 들어, {0, 1, 2, 3}과 {0, 2, 4, 6}이 주어진다면 결과는 {0, 1, 2, 3, 4, 6}이 됩니다. 만약 0이나 2처럼 요소가 양쪽 열 모두에 존재한다면 첫째 열에 있는 요소가 복사됩니다.

#include <algorithm>
string str1[] = {"Pooh", "Piglet", "Tigger", "Eerore"};
string str2[] = {"Pooh", "Heffalump", "Woozles"};

set<string> set1(str1, str1 + 4), set2(str2, str2 + 3);

/* 각각의 set 연산의 결과를 저장합니다. */ 
set<string> res;

/* set_union(): Eeyore Heffalump Piglet Pooh Tigger Woozles */ 
set_union(set1.begin(), set1.end(), set2.begin(), set2.end(), inserter(res, res.begin()));

res.clear();

/* set_intersection(): Pooh */ 
set_intersection(set1.begin(), set1.end(), set2.begin(), set2.end(), inserter(res, res.begin()));

res.clear();

/* set_difference(): Eeyore Piglet Tigger */ 
set_difference(set1.begin(), set1.end(), set2.begin(), set2.end(), inserter(res, res.begin()));

res.clear();

/* set_symmetric_difference(): Eeyore Heffalump Piglet Tigger Woozles */ 
set_symmetric_difference(set1.begin(), set1.end(), set2.begin(), set2.end(), inserter(res, res.begin()));

sort(), stable_sort()
기본적으로, 보다 작은가의 비교 연산자를 이용해서 오름차순으로 요소들을 정렬합니다. 선택적인 세 번째 매개변수에 다른 정렬 연산을 지정할 수 있습니다. stable_sort()는 컨테이너 내의 상대적인 요소들의 순서를 유지시킵니다. 예를 들어, 알파멧순으로 단어를 정렬했고, 이제 단어의 길이로 정렬하려고 합니다. 이를 위해 두 문자열을 길이로 비교할 수 있는 ?LessThan 함수 객체를 넘깁니다. sort()를 사용한다면 알파벳 순서가 유지된다고 보증할 수 없습니다.

#include <algorithm>
stable_sort(ia, ia + 8);
stable_sort(svec.begin(), svec.end(), greater<string>());

transform()
transform()의 첫 번째 형태는 열의 각 요소에 매개변수로 넘긴 당항 연산자를 적용시킵니다. 예를 들어, {0, 1, 1, 2, 3, 5}와 각각의 요소를 2배로 하는 Double의 함수 객체가 주어졌다고 가정하면 결과는 {0, 2, 2, 4, 6, 10}이 됩니다. 두 번째 형태는 두 열의 관련된 요소에 매개변수로 넘긴 이항 연산자를 적용시킵니다. 예를 들어, {1, 3, 5, 9}와 {2, 4, 6, 8} 그리고 두 요소를 더한 뒤 그 합을 2배로 만드는 ?AddAndDouble 함수 객체가 주어졌다면 결과는 {6, 14, 22, 34}가 됩니다. 결과 열은 첫 번째 형태에서는 세 번째 반복자에, 두 번째 형태에서는 네 번째 반복자에 복사됩니다.

#include <algorithm>
int double_val(int val) { return val + val; }
int difference(int val1, int val2) { return abs(val1 - val2); }

int ia[] = {3, 5, 8, 13, 21};
vector<int> vec(5), vec2(5);

/* 첫 번째 형태: 6 10 16 26 42 */ 
transform(ia, ia + 5, vec.begin(), double_val);

/* 두 번째 형태: 3 5 8 13 21 */ 
transform(ia, ia + 5, vec.begin(), vec2.begin(), difference);

unique(), unique_copy()
상등 연산자를 사용해서 같은 값들이 연속적으로 있는 그룹들을 하나의 요소로 합칩니다. 상든 연산을 오버라이딩해서 다른 비교 연산을 넘길 수도 있습니다. Mississippi란 단어는 그 결과가 Misisipi가 됩니다. 세 개가 연속적이지 않기 때문에 다 합쳐지지는 않습니다. 중복되는 모든 요소들을 합치려면 먼저 컨테이너를 정렬해야 합니다. remove()에서처럼 컨테이너의 실제 크기는 변하지 않습니다. 각각의 고유한 요소들은 차례로 빈 슬롯에 대입됩니다. 예제에서 물리적인 결과는 Misisipippi입니다. ppi란 문자열은 알고리즘의 나머지 조각을 나타냅니다. 반환됩 반복자는 이 부분을 가리킵니다. 일반적으로, 이 반복자를 erase()에 넘깁니다(기본 배열은 erase() 연산을 지원하지 않기 때문에 unique()가 적합하지 않습니다. 그 대신 unique_copy()가 보다 적합합니다).

#include <algorithm>
int ia[] = {0, 1, 0, 2, 0, 3, 0, 4, 0, 5};
vector<int> vec(ia, ia + 10);

sort(vec.begin(), vec.end());
iter = unique(vec.begin(), vec.end());
vec.erase(vec_iter, vec.end());  /* vec: 0 1 2 3 4 5 */

int ia2[10];
sort(ia, ia + 10);
unique_copy(ia, ia + 10, ia2);

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 항목은 *(으)로 표시합니다