반응형
반응형

1. STL에서 제공하는 산술 연산 함수 객체

함수명 내용 인자
plus<T> 더하기 이항
minus<T> 빼기 이항
multiplies<T> 곱하기 이항
divides<T> 나누기 이항
modulus<T> 나머지 이항
negate<T> 부호 변경 단항

2. 사용 법

  1. plus<T>
    • 헤더 추가 : <functional>
    • 일반적으로 아래 방법 사용
    • plus<int>()(10, 20);
plus<int> Plus;   // 객체 생성

// 1. 암묵적 호출
oPlus(10, 20);

// 2. 명시적 호출
oPlus.operator()(10,20);

// 3. 임시 객체로 암묵적 호출(일반적인 사용)
plus<int>()(10,20);

// 4. 임시 객체로 명시적 호출
plus<int>().operator()(10,20);

3. 알고리즘과 같이 사용하는 예

vector<int> v1 = {10,20,30,40,50};
vector<int> v2 = {1,2,3,4,5};
vector<int> v3(5);

//1. plus<int>()
transform(v1.begin(), v1.end(), v2.begin(), v3.begin(), plus<int>());
// v3 = {11,22,33,44,55}

//2. multiplies<int>()
transform(v1.begin(), v1.end(), v2.begin(), v3.begin(), multiplies<int>());
// v3= {10, 40, 90,  160, 250}

//3. negate<int>() : 부호 변경
transform(v1.begin(), v1.end(), v3.begin(), negate<int>());
// v3 = {-10, -20, -30, -40, -50}

// 4. minus<int>() + 인접 원소와의 차이
adjacent_difference(
   v1.begin(),
   v1.end(),
   v3,begin(),
   minus<int>()
);
// v3 = {10, 10, 10, 10, 10}

// 5.multiplies<int>() + 곱 누적
partial_sum(
   v1.begin(),
   v1.end(),
   v3.begin(),
   multiplies<int>()
);
// v3 = {10, 200, 6000, 240000, 12000000}

// 6.multiplies<int>() + 모든 원소 곱
int mul = accumulate(
   v1.begin(),
   v1.end(),
   1,
   muliplies<int>()
);
// mul = 12000000

참고

  1. 뇌를 자극하는 C++ STL
반응형
반응형

1. 용어 정리

  1. 함수 객체란?
    • operator() 연산자를 오버로딩한 클래스 객체
    • 다른 이름으로 functor(함수자)라고 불림
  2. 함수류 : 함수 객체, 함수, 함수 포인터

2. 함수 객체 종류

  1. 일반 함수 객체 : 특정 기능을 수행

    • 산술 연산 함수 객체 : 산술 연산 기능 수행
    • 비교 연산 함수 객체 조건자 : 비교 조건자
  2. 함수 어댑터 : 함수류를 인자로 받아 다른 함수 객체로 변환

    • 바인더: 이항 함수 객체를 단항 함수 객체로 변환
    • 부정자 : 함수 객체 조건자를 반대로 변환
    • 함수 포인터 어댑터 : 함수 포인터를 STL이 요구하는 함수 객체로 변환
    • 멤버 함수 포인터 어댑터 : 멤버 함수 포인터를 함수 객체로 변환

3. 조건자

  1. bool 형식을 반환하는 함수류
    • 함수 객체 조건자
    • 함수 조건자
    • 함수 포인터 조건자
  2. STL에서 조건자?
    • 모두 함수 객체 조건자
    • 조건자는 객체의 상태값을 변경할 수 없음
    • operator() 연산자 오버로딩 함수는 모두 const

4. 어댑터

  1. 함수 객체를 다른 함수 객체로 변환할 때 사용
  2. 어댑터 인자로 사용되는 단항 함수 필요 조건
    • argument_type 정의 필요
    • result_type 정의 필요
  3. 어댑터 인자로 사용되는 이항 함수 필요 조건
    • first_argument_type 정의
    • second_argument_type 정의
    • result_type 정의
template<typename T>
struct Plus{
   typedef T first_argument_type;
   typedef T second_argument_type;
   typedef T result_type;

   T operator()(const T& left, const T& right) const{
      return left + right;
   }
};

vector<int> v1 = {10,20,30};
vector<int> v3(3);

// Plus 함수를 단항 함수로 변경
transform(
   v1.begin(),
   v1.end(),
   v3.begin(),
   binder1st<Plus<int>> (Plus<int>(), 100)
   );
// v3 = {110, 120 , 130}
  1. 단항, 이항 함수 형식 정의 방법
    • 위 조건 정의 대신 아래 클래스 상속
    • unary_function : 단항 함수 정의시
    • binary_function : 이항 함수 정의시
template<typename T>
struct Plus: public binary_function<T,T,T>{
   T operator()(const T& left, const T& right) const{
      return left+right;
   }
};

vector<int> v1 = {10,20,30};
vector<int> v3(3);

// Plus 함수를 단항 함수로 변경
transform(
   v1.begin(),
   v1.end(),
   v3.begin(),
   binder1st<Plus<int>> (Plus<int>(), 100)
   );
// v3 = {110, 120 , 130}

참고

  1. 뇌를 자극하는 C++ STL
반응형
반응형

0. 수치 알고리즘

  1. <numeric> 헤더에 포함됨

1. 수치 리스트

알고리즘 설명
x2=accumulate(b,e,x) x2는 x를 초기값으로 시작한 구간 [b,e) 순차열 원소의 합
x2=accumulate(b,e,x,f) x2는 x를 초기값으로 시작한 구간 [b,e) 순차열 원소의 누적. f를 누적에 사용
x2=inner_product(b,e,b2,x) x2는 x를 초기값으로 시작한 구간 [b,e)와 구간 [b2,b2+e-b)의 내적(두 순차열의 곱의 합)
x2=inner_product(b,e,b2,x,f1,f2) x2는 x를 초기값으로 시작한 구간 [b,e)와 구간 [b2,b2+e-b)의 모든 원소끼리 f2 연산 후 f1연산으로 총 연산한 결과
p=adjacent_difference(b,e,t) 구간 [b,e)의 인접 원소와의 차를 순차열 [t,p)에 저장
p=adjacent_difference(b,e,t,f) 구간 [b,e)의 인접 원소와의 연산을 순차열 [t,p)에 저장. f를 연산에 사용
p=partial_sum(b,e,t) 구간 [b,e)의 현재 원소까지의 합을 순차열 [t,p)에 저장
p=partial_sum(b,e,t,f) 구간 [b,e)의 현재 원소까지의 연산을 순차열 [t,p)에 저장. f를 연산에 사용

2. 상세 내용

  1. accumulate(b,e,x)
    • 순차열 원소의 합을 구함
vector<int> v = {10,20,30,40,50};
int sum = accumulate(v.begin(), v.end(), 0);
// sum = 150 = 0+10+20+30+40+50

int sum2 = accumulate(v.begin(), v.end(), 100);
// sum = 250 = 100+10+20+30+40+50+
  1. accumulate(b,e,x,f)
    • 순차열 원소에 f함수 적용 가능
    • f는 이항 함수
    • 함수에 따라 누적합,누적곱 등 연산 가능
// 1. Functor
template<typename T>
struct Plus{
   T operator() (const T& left, const T& right){
      return left+right;
   }
};

// 2. 클라이언트
void main(){
   vector<int> v = {1,2,3,4,5};
   // 사용자가 정의한 합함수
   int a = accumulate(v.begin(), v.end(), 0, Plus<int>());
   // a = 15 = 0+1+2+3+4+5

   // stl multiplies
   int mul = accumulate(v.begin(), v.end(), 1, multiplies<int>());
   // mul = 120 = 1 * 1 * 2 * 3 * 4 * 5
}
// 3. 서버
T accumulate(Iterator first, Iterator last, T x, Function fun){
   T ret = x;
   for(Iterator p = first; p != last ; ++p){
      ret = fun(ret, *p);
   }
   return ret;
}
  1. inner_product(b,e,b2,x)
    • 두 순차열의 내적 계산
vector<int> v1 = {1,2,3,4,5};
vector<int> v2 = {2,2,2,2,2};

int in = inner_product(v1.begin(), v1.end(), v2.begin(), 100);
// in = 130 = 100 + 1*2 + 2*2 + 3*2 + 4*2 + 5*2
  1. inner_product(b,2,b2,x,f1,f2)
    • 다양한 원소 간의 연산과 누적 연산 수행 가능
    • 두 순차열의 원소끼리의 차이의 합을 계산하는 예제
int Plus(int left, int right){
   return left+right;
}

int Minus(int left, int right){
   return left-right;
}

vector<int> v1 = {10,20,30,40,50};
vector<int> v2 = {2,2,2,2,2};

int a = inner_product(
   v1.begin(), v1.end()
   , v2.begin(), 0, Plus, Minus);
// a = 140 = 0 + 10 -2 + 20 - 2 + 30 -2 + 40 -2 + 50 - 2

//서버 예시
T inner_product(Iter first, Iter first2, T x, Func1 fun1, Func2 fun2){
   T ret = x;
   for(Iter p = first, q = first2; p != last; ++p, ++q){
      ret = fun1(ret, fun2(*p,*q))
   }
   return ret;
}
  1. adjacent_difference(b,e,t)
    • 순차열에서 연속한 원소 간의 차 계산
vector<int> v1 = {10,20,30,40,50};
vector<int> v2(5);
auto iter = adjacent_difference(
   v1.begin(), v1.end(), v2.begin()
);
// v2 = {10, 10, 10, 10, 10}
// 1번 10 => 10
// 2번 10 => 20 - 10
// ...
// iter - 1 = > 마지막 10을 가리킴
  1. adjacent_difference(b,e,t,f)
    • 인접 원소와의 사용자 정의 함수 수행
    • EX) 인접 원소 합을 저장
int Plus(int left, int right){
   return left + right;
}

vector<int> v1 = {10,20,30,40,50}
vector<int> v2(5);
auto iter = adjacent_difference(
   v1.begin(), v1.end(), v2.begin(), Plus
);
// v2 = {10, 30, 50, 70, 90}
// 10 => 10
// 30 => 10 + 20
// ...
// iter - 1 = 90을 가리킴
  1. partial_sum(b,e,t)
    • 순차열에서 시작부터 매 현재 원소까지의 합을 구함
vector<int> v1 = {10,20,30,40,50};
vector<int> v2(5);

auto iter = partial_sum(
   v1.begin(), v1.end(), v2.begin()
);
// v2 = {10, 30, 60, 100, 150}
// 10 => 10
// 30 => 10 + 20
// 60 => 10 + 20 + 30
// ...
// iter - 1 => 150을 가리킴
  1. partial_sum(b,e,t,f)
    • 순차열에서 시작부터 매 현재 원소까지의 사용자 정의 연산을 수행함
int Multi(int left, int right){
   return left * right;
}

vector<int> v1 = {10,20,30,40,50};
vector<int> v2(5);

auto iter = partial_sum(v1.begin(), v1.end(), v2.begin(), Multi);
// v2 = { 10, 200, 6000, 240000, 12000000}
// 10 => 10
// 200 => 10 * 20
// 6000 => 10 * 20 * 30
// ...
// iter - 1 => 12000000을 가리킴

참고

  1. 뇌를 자극하는 C++ STL
반응형
반응형

0. 정렬된 범위 알고리즘

  1. 정렬된 구간에서만 동작하는 알고리즘
  2. 원소가 같음 비교시 a==b 연산 사용 안함
  3. 원소가 같은 비교시 !(a<b) && !(b<a) 사용

1. 정렬 알고리즘 리스트

알고리즘 설명
binary_search(b,e,x) 구간 [b,e)의 순차열에 x와 같은 원소가 있는가?
binary_search(b,e,x,f) 구간 [b,e)의 순차열에 x와 같은 원소가 있는가? f를 비교에 사용
includes(b,e,b2,e2) 구간 [b2,e2)의 모든 원소가 구간 [b,e)에도 있는가?
includes(b,e,b2,e2,f) 구간 [b2,e2)의 모든 원소가 구간 [b,e)에도 있는가? f를 비교에 사용
p=lower_bound(b,e,x) p는 구간 [b,e) 순차열에서 x와 같은 첫 원소의 반복자
p=lower_bound(b,e,x,f) p는 구간 [b,e) 순차열에서 x와 같은 첫 원소의 반복자. f는 비교에 사용
p=upper_bound(b,e,x) p는 구간 [b,e) 순차열에서 x 보다 큰 첫 원소의 반복자
p=upper_bound(b,e,x,f) p는 구간 [b,e) 순차열에서 x 보다 큰 첫 원소의 반복자. f를 비교에 사용
pair(p1,p2)=equal_range(b,e,x) 구간 [p1,p2)의 순차열은 구간 [b,e)의 순차열에서 x와 같은 원소의 구간. [lower_bound(), upper_bound())의 순차열과 같음
pair(p1,p2)=equal_range(b,e,x,f) equal_range(b,e,x)와 동일. f를 비교에 사용
p=merge(b,e,b2,e2,t) 구간[b,e)의 순차열과 구간 [b2,e2)의 순차열을 합병해 [t,p)에 저장
p=merge(b,e,b2,e2,t,f) merge(b,e,b2,e2,t)과 동일. f를 비교에 사용
inplace_merge(b,m,e) 정렬된 [b,m) 순차열과 [m,e) 순차열을 [b,e)순차열로 합병
inplace_merge(b,m,e,f) inplace_merge(b,m,e,f)와 동일. f를 비교에 사용
p=set_union(b,e,b2,e2,t) 구간 [b,e)의 순차열과 [b2,e2)의 순차열을 정렬된 합집합으로 [t,p)에 저장
p=set_union(b,e,b2,e2,t,f) set_union(b,e,b2,e2,t)와 동일. f를 비교에 사용
p=set_intersection(b,e,b2,e2,t) 구간 [b,e)의 순차열과 [b2,e2)의 순차열을 정렬된 교집합으로 [t,p)에 저장
p=set_intersection(b,e,b2,e2,t,f) set_intersection(b,e,b2,e2,t)과 동일. f를 비교에 사용
p=set_difference(b,e,b2,e2,t) 구간 [b,e)의 순차열과 [b2,e2)의 순차열을 정렬된 차집합 [t,p)에 저장
p=set_difference(b,e,b2,e2,t,f) set_difference(b,e,b2,e2,t)과 동일. f를 비교에 사용
p=set _symmetric_difference(b,e,b2,e2,t) 구간 [b,e)의 순차열과 [b2,e2)의 순차열을 정렬된 대칭 차집합으로 [t,p)에 저장
p=set _symmetric_difference(b,e,b2,e2,t,f) set _symmetric_difference(b,e,b2,e2,t)와 동일. f를 비교에 사용

2. 상세 예시

  1. binary_search(b,e,x)

    • 구간 [b,e)에서 x와 같은 원소가 있음 true
vector<int> v = {10,20,30,40,50};
bool b = binary_search(v.begin(), v.end(), 20);
// b = true
  1. binary_search(b,e,x,f)
    • f를 조건자(이항 함수)로 사용하여 찾음
bool Pred(int left, int right){
   return 3 < right - left;
} // 오른쪽이 왼쪽보다 3보다 크면 참

vector<int> v = {40,46,12,80,10,47,30,55,90,53};
sort(v.begin(), v.end(), Pred);
// 조건자에 의한 정렬
// v = {12,10,30,40,46,47,55,53,80,90}
// 12와 10의 차이가 3보다 작기 때문에 12가 앞
// 55와 53의 차이가 3보다 작기 때문에 55가 앞

bool b = binary_search(v.begin(), v.end(), 32, Pred);
// b = true
// !Pred(30,32) => true 이고,
// !Pred(32,30) => true 이므로,
// 참조건 (!Pred(30,32)&&!Pred(32,30)) = true
  1. includes(b,e,b2,e2)
    • [b,e) 에 [b2,e2)가 포함되면 true
vector<int> v = {10,20,30,40,50};
vector<int> v2 = {10,20,40};
vector<int> v3 = {10,20,60};

bool b1 = includes(v1.begin(), v1.end()
                  ,v2.begin(), v2.end());
// b1 = true
// v2는 v에 포함되므로

bool b2 = includes(v1.begin(), v1.end(), v2.begin(), v2.end());
// b2 = false
// v3의 60은 v에 포함되지 않으므로

//조건자 사용
sort(v1.begin(), v1.end(), greater<int>());
sort(v2.begin(), v2.end(), greater<int>());
b1 = includes(v1.begin(), v1.end()
            , v2.begin(), v2.end()
            , greater<int>())
  1. lower _bound, upper _bound, equal_range
    • 찾는 원소가 여러 개 일 때 반복자 반환
    • lower_bound : 첫 원소의 반복자 반환
    • upper_bound : 마지막 다음 원소 반복자 반환
    • equal_range : [lower_bound, upper_bound) pair 반환
vector<int> v = {10,20,30,30,30,40,50};

auto lower = lower_bound(v.begin(), v.end(), 30);
auto upper = upper_bound(v.begin(), v.end(), 30);
auto eual = equal_range(v.begin(), v.end(), 30);
// lower = 첫 30을 가리킴
// upper = 마지막 30의 다음 40을 가리킴
// eqaul = (lower,upper)의 pair 형태
  1. merge(b,e,b2,e2,t)
    • 정렬된 두 순차열을 목적지 순차열로 병합
vector<int> v1 = {10,20,30,40,50};
vector<int> v2 = {20,30,60};
vector<int> v3(10);

auto iter = merge(v1.begin(), v1.end()
                 ,v2.begin(), v2.end()
                 ,v3.begin());
// v3 = {10,20,20,30,30,40,50,60,0,0};
// iter -1 => 60을 가리킴
  1. inplace_merge(b,m,e)
    • 하나의 순차열이 두 구간으로 정렬되어 있을 때
    • 하나의 구간으로 정렬 가능
vector<int> v = {10,20,30,40,50,20,30,60};
// v => 10,20,30,40,50 과
// 20,30,60 의 두 개의 구간으로 정렬되어 있음

inplace_merge(v.begin(), v.begin()+5, v.end());
// v = {10,20,20,30,30,40,50,60} 으로 정렬됨

3. 집합 관련 알고리즘

  1. set_union(b,e,b2,e2,t)
    • 두 순차열의 합집합을 구함
  2. set_intersection(b,e,b2,e2,t)
    • 두 순차열의 교집합을 구함
  3. set_difference(b,e,b2,e2,t)
    • 두 순차열의 차집합을 구함
  4. set_ symmetric_difference(b,e,b2,e2,t)
    • 두 순차열의 대칭 차집합을 구함
vector<int> v1 = {10,20,30,40,50};
vector<int> v2 = {20,30,60};
vector<int> v3(10);

// 1. 합집합
auto iter = set_union(
   v1.begin(), v1.end()
  ,v2.begin(), v2.end()
  ,v3.begin());
// v3 = {10,20,30,40,50,60,0,0,0,0}
// iter - 1 => 60을 가리킴

// 2. 교집합
auto iter = set_intersection(
   v1.begin(), v1.end()
  ,v2.begin(), v2.end()
  ,v3.begin());
// v3 = {20,30,0,0,0,0,0,0,0,0}
// iter - 1 => 30을 가리킴

// 3.차집합
auto iter = set_difference(
   v1.begin(), v1.end()
  ,v2.begin(), v2.end()
  ,v3.begin());
// v3 = {10,40,50,0,0,0,0,0,0,0}
// iter - 1 => 50을 가리킴

// 4. 대칭 차집합
auto iter = set_symmetric_difference(
   v1.begin(), v1.end()
  ,v2.begin(), v2.end()
  ,v3.begin());
// v3 = {10,40,50,60,0,0,0,0,0,0}
// iter - 1 => 60을 가리킴

참고

  1. 뇌를 자극하는 C++ STL
반응형
반응형

0. 정렬 알고리즘

  1. 변경 알고리즘의 특수한 형태
  2. 특정 정렬 기준으로 원소의 순서를 변경 및 정렬

1. 정렬 알고리즘 리스트

알고리즘 설명
make_heap(b,e) 힙을 생성. 구간 [b,e)의 순차열을 힙 구조로 변경
make_heap(b,e,f) make_heap(b,e)와 동일. f는 조건자로 비교에 사용.
push_heap(b,e) 힙에 원소 추가. push_back와 같이 사용. 구간 [b,e)의 순차열을 다시 힘 구조가 되게 함.
push_heap(b,e,f) push_heap(b,e)와 동일. f는 조건자로 비교에 사용
pop_heap(b,e) 힙에서 원소 제거. 구간 [b,e)의 순차열의 가장 큰 원소(첫 원소)를 제거.
pop_heap(b,e,f) pop_heap(b,e)와 동일. f는 조건자로 비교에 사용.
sort_heap(b,e) 힙을 정렬. 구간 [b,e)의 순차열을 힙 구조를 이용해 정렬
sort_heap(b,e,f) sort_heap(b,e)와 동일. f는 조건자로 비교에 사용
nth_element(b,m,e) 구간 [b,e)의 원소 중 m-b개 만큼 선별된 원소를 [b,m) 순차열에 놓이게 함
nth_element(b,m,e,f) nth_element(b,m,e) 와 동일. f는 조건자로 비교에 사용
sort(b,e) 구간 [b,e)를 퀵 정렬 기반으로 정렬
sort(b,e,f) sort(b,e) 와 동일. 조건자 f를 사용해 정렬.
stable_sort(b,e) 구간 [b,e)를 머지 정렬을 기반으로 정렬. 값이 같은 원소의 상대적 순서 유지.
stable_sort(b,e,f) stable_sort(b,e)와 동일. f는 조건자로 비교에 사용.
partial_sort(b,m,e) 힙 정렬 기반으로 정렬. 구간 [b,e) 원소 중 m-b개 만큼 상위 원소를 정렬하여 [b,m) 순차열에 놓음
partial_sort(b,m,e,f) partial_sort(b,m,e) 와 동일. f는 조건자로 비교에 사용.
partial _sort_copy(b,e,b2,e2) 힙 정렬 기반으로 정렬. 구간 [b,e) 원소 중 상위 e2-b2개의 원소만 정렬하여 [b2,e2)로 복사
partial _sort_copy(b,e,b2,e2,f) partial _sort_copy(b,e,b2,e2)와 동일. f는 조건자로 비교에 사용.

2.힙 관련 알고리즘

  1. 자료 구조 힙
    • 완전 이진 트리로 구성
    • 트리 내의 모든 원소가 부모 노드보다 큰 값(또는 작은 값)을 가짐
    • 루트 노드는 항상 가장 작은 값(또는 가장 큰 값)을 가짐
    • 최대값, 최소값 연산이 빠름
  2. 힙의 연산
    • 추가 연산
      • 완전 이진 트리 가장 끝에 원소 추가
      • 힙의 규칙을 깨지 않게 교환하여 힙을 유지
    • 제거 연산
      • 루트 노드를 삭제
      • 삭제된 루트 노드에 힙의 마지막 노드 가져옴
      • 힙의 규칙 깨지 않게 교환하여 힙을 유지
  3. heap 예제
    • min heap : v = {1,3,2,4,6,5}
    • max heap : v = {6,5,3,4,2,1}
  4. make_heap(b,e)
    • 구간 [b,e)의 순차열을 힙 구조로 만듦
vector<int> v = {10,20,30,40,50,60};
// 1. 최대 heap 생성
make_heap(v.begin(), v.end());
// v = {60,50,30,40,20,10}

// 2. 최소 heap 생성
make_heap(v.begin(), v.end(), greater<int>());
// v= {10,20,50,30,40,60}
  1. push_heap(b,e)
    • 원소가 추가된 상태에서 사용
    • 추가된 구간 [b,e) heap을 교환하여 heap을 유지함.
    • 일반적으로 push_back()과 함께 사용
//위의 예제 수행 후
v.push_back(35);
// 마지막에 단순 원소 추가
// v = {60,50,30,40,20,10,35}
push_heap(v.begin(), v.end());
// v = {60,50,35,40,20,10,30}
// heap 형태를 재계산
  1. pop_heap(b,e)
    • root node를 (논리적)제거(제일 마지막으로 이동)
    • 원리
      • root node와 마지막 node를 교환
      • heap을 유지하도록 교환 반복
vector<int> v = {10,20,30,40,50,60};
make_heap(v.begin(), v.end());
// v = {60,50,30,40,20,10}
pop_hep(v.begin(), v.end());
// v= {50,40,30,10,20,60}
  1. sort_heap(b,e)
    • 구간 [b,e)를 heap 정렬
    • 구간 [b,e)가 heap 구조여야 함
vector<int> v = {10,20,30,40,50,60};
make_heap(v.begin(), v.end());
// v = {60,50,30,40,20,10}
sort_heap(v.begin(), v.end());
// v= {10,20,30,40,50,60}

3. 기타 정렬 알고리즘 상세

  1. nth_element(b,m,e)
    • 전체 구간 [b,e) 에서 구간 [b,m) 만큼의 순차열을 부분적으로 정렬
    • 주로 n 개의 요소를 선별할 때 사용
    • 또는 n 번째 요소가 필요할 때 사용
vector<int> v = {10,30,20,40,50,60};
nth_element(v.begin(), v.begin() + 1, v.end());
// 두번째로 작은 값 : v[1] = 20
  1. sort(b,e)
    • 퀵 정렬을 기반으로 정렬
vector<int> v = {5,1,3,2,7,9,8};
//오름차순 정렬(less: defualt)
sort(v.begin(), v.end());
// v = {1,2,3,5,7,8,9}

//내림차순 정렬(greater)
sort(v.begin(), v.end(), greater<int>());
// v = {9,8,7,5,3,2,1}
  1. stable_sort(b,e)
    • 머지 정렬을 기반으로 정렬
    • 같은 원소의 상대적인 순서를 유지할 때 사용
vector<int> v= {30,50,30,20,40,10,40};
//오름차순 정렬(less: defualt)
stable_sort(v.begin(), v.end());
// v = {10,20,30,30,40,40,50}

//내림차순 정렬(greater)
stable_sort(v.begin(), v.end(), greater<int>());
// v = {50,40,40,30,30,20,10}
  1. partial_sort(b,m,e)
    • heap정렬 기반으로 정렬
    • 순차열의 상위 구간만 정렬할 때 사용
    • heap정렬의 특징이 필요할 때 사용
    • m과 e가 같다면 전체 원소를 정렬함
vector<int> v = {10,30,20,40,50,60};
partial_sort(v.begin(), v.begin() + 3, v.end());
// v.begin() 부터 3개까지만 heap 정렬함
// v = {10,20,30,40,50,60}
  1. partial _sort_copy(b,e,b2,e2)
    • 구간 [b,e) 를 heap정렬 하고,
    • 구간 [b2,e2)에 정렬 결과를 저장함.
vector<int> v = {10,30,20,40,50,60};
vector<int> v2(3);
partial_sort_copy(v.begin(), v.end(), v2.begin(), v2.end());
// v.begin() 부터 3개까지만 heap 정렬함
// v2 = {10,20,30}

참고

  1. 뇌를 자극하는 C++ STL
  2. https://velog.io/@nninnnin7/HEAP
반응형
반응형

0. 변경 알고리즘

  1. 순차열 원소의 '순서'를 변경하는 알고리즘
    • 순차열의 원소를 교환
    • 순차열의 원소를 이동

1. 변경 알고리즘 리스트

알고리즘 설명
bool=next_permutation(b,e) 구간 [b,e)의 순차열을 사전순 다음 순열이 되게 함. 더 이상 다음 순열이 없는 마지막 순열이라면 bool은 false
bool=next_permutation(b,e,f) 구간 [b,e)의 순차열을 사전순 다음 순열이 되게 함. 비교에 f를 사용. 더 이상 다음 순열이 없는 마지막 순열이라면 bool은 false를 반환
bool=prev_permutation(b,e) 구간 [b,e)의 순차열을 사전순 이전 순열이 되게 함. 더 이상 이전 순열이 없는 첫 순열이라면 bool은 false를 반환
bool=prev_permutation(b,e,f) 구간 [b,e)의 순차열을 사전순 이전 순열이 되게 함. 비교에 f를 사용. 더 이상 이전 순열이 없는 첫 순열이라면 bool은 false
p=partition(b,e,f) 구간 [b,e)의 순차열 중 f(*p)가 참인 원소는 [b,p)의 순차열에 거짓인 원소는 [p,e)의 순차열로 분류
random_shuffle(b,e) 구간 [b,e)의 순차열을 랜덤(기본 랜덤기)로 뒤섞음
random_shuffle(b,e,f) 구간 [b,e)의 순차열을 f를 랜덤기로 사용하여 뒤섞음
reverse(b,e) 구간 [b,e)의 순차열을 뒤집음
p=reverse_copy(b,e,t) 구간 [b,e) 순차열을 뒤집어 목적지 순차열 [t,p)에 복사함
rotate(b,m,e) 구간 [b,e)의 순차열을 왼쪽으로 회전. 첫 원소와 마지막 원소가 연결된 것 처럼 모든 원소가 왼쪽으로 (m-b) 만큼 이동
p=rotate_copy(b,m,e,t) 구간 [b,e)의 순차열을 회전하여 목적지 순차열 [t,p)에 복사
stable_partition(b,e,f) partition() 알고리즘과 같고 원소의 상대적인 순서를 유지함

2. 상세 예시

  1. next_permutation(b,e)
    • 예시) v = 10,20,30
    • 6가지 순열을 만듦
vector<int> v = {10,20,30}
while(next_permutation(v.begin(), v.end())){
// 1. v = {10, 30, 20} , b = true
// 2. v = {20, 10, 30} , b = true
// 3. v = {20, 30, 10} , b = true
// 4. v = {30, 10, 20} , b = true
// 5. v = {30, 20, 10} , b = true
// 6. v = {10, 20, 30} , b = false
}
  1. next_permutation(b,e,f)
    • 이항 조건자 f를 기준으로 순열 만듦
bool Pred(const Point& left, const Point& right){
   return left.getY() < right.getY();
}  // Point의 y좌표가 오른쪽이 더 크면 true

vector<Point> v;
v.push_back(Point(5,1));
v.push_back(Point(7,2));
v.push_back(Point(5,3));

while(next_permutation(v.begin(), v.end(), Pred)){
   // 1. v = {(5,1), (5,3), (7,2)}, b = true
   // 2. v = {(7,2), (5,1), (5,3)}, b = true
   // 3. v = {(7,2), (5,3), (5,1)}, b = true
   // 4. v = {(5,3), (5,1), (7,2)}, b = true
   // 5. v = {(5,3), (7,2), (5,1)}, b = true
   // 6. v = {(5,1), (7,2), (5,3)}, b = false
}
  1. partition(b,e,f)
    • 순차열의 원소를 특정 조건에 따라 분류
    • 원리 : quick sort 에서 pivot 값을 기준으로 큰값과 작은값을 분류하듯 분류함
    • 30,40,50,10,20,60 => 30 그대로
    • 30,20,50,10,40,60 => 40,20 교환
    • 30,20,10,50,40,60 => 50,10 교환
bool Pred(int n){
   return n < 40;
} // 40 작으면 참

// 1. partition
vector<int> v = {30,40,50,10,20,60};
auto iter = partition(v.begin(), v.end(), Pred);
// v = 30,20,10,50,40,60
// iter -1 => 10을 가리킴
// [begin,iter) => {30,20,10}
// [iter,end) => {50,40,60}

// 2.stable_partition
vector<int> v2 = {30,40,50,10,20,60};
iter = stable_partition(v2.begin(), v2.end(), Pred);
// v = 30,10,20,40,50,60
// iter -1 => 20을 가리킴
// [begin,iter) => {30,10,20}
// [iter,end) => {40,50,60}
  1. stable_partition(b,e,f)

    • partition와의 차이 => 원소의 상대적인 순서를 변경안함
    • 위의 예제 참고
    • 원리
    • 30,40,50,10,20,60 => 30 그대로
    • 30,10,50,40,20,60 => 40, 10 교환
    • 30,10,20,40,50,60 => 50, 20 교환
  2. random_suffle(b,e)

    • 구간 [b,e)의 순차열을 랜덤으로 섞음
    • 초기화는 <cstdlib> 헤더의 srand() 사용
vector<int> v = {10,20,30,40,50};
random_shuffle(v.begin(), v.end());
// {50,20,40,30,10} : 랜덤으로 값 뒤섞임
  1. reverse(b,e)
    • 구간 [b,e)의 원소를 뒤집는다.
vector<int> v = {10,20,30,40,50};
reverse(v.begin(), v.end());
// v = {50,40,30,20,10}
  1. reverse_copy(b,e,t)
    • 뒤집은 순차열을 구간 [t,p)에 저장
vector<int> v1 = {10,20,30,40,50};
vector<int> v2(5);
auto iter = reverse_copy(v1.begin(), v1.end(), v2.begin());
// v2 = {50,40,30,20,10}
// iter - 1 => 10을 가리킴
  1. rotate(b,m,e)
    • 순차열을 회전
    • m 이 begin이 되고, (m-b) 만큼 이동함
vector<int> v = {10,20,30,40,50};

rotate(v.begin(), v.begin() + 2, v.end());
// v = {30,40,50,10,20} : 2만큼 회전
  1. rotate_copy(b,m,e,t)
    • 순차열을 회전하여 [t,p)에 복사
vector<int> v1 = {10,20,30,40,50};
vector<int> v2(5);
auto iter = rotate_copy(v1.begin(), v1.begin() + 2, v1.end(), v2.begin());
//v2 = {30,40,50,10,20}

참고

뇌를 자극하는 C++ STL

반응형
반응형

0. 제거 알고리즘

  1. 원소를 수정하는 알고리즘의 특수한 형태
  2. 원소를 실제로 제거하지 않음
  3. 논리적으로 제거(다음 원소로 덮어쓰기)함
  4. 순차열의 size를 실제로 변경하지 않음
  5. 실제 size 변경 필요시 컨테이너의 erase함수 사용

1. 제거 알고리즘 리스트

알고리즘 설명
p=remove(b,e,x) 구간 [b,e)의 순차열에서 x 원소가 남지 않도록 덮어쓰기로 이동. 알고리즘 수행 후 순차열은 [b,p)가 됨
p=remove_if(b,e,f) 구간 [b,e)의 순차열을 f(*p)가 참인 원소가 남지 않도록 덮어쓰기로 이동. 알고리즘 수행 후 순차열을 [b,p)가 됨
p=remove_copy(b,e,t,x) 구간 [b,e)의 순차열에서 *p==x가 아닌 원소만 순차열 [t,p)에 복사
p=remove _copy_if(b,e,t,f) 구간 [b,e)의 순차열에서 f(*p)가 참이 아닌 원소만 순차열 [t,p) 에 복사
p=unique(b,e) 구간 [b,e) 순차열을 인접한 중복 원소가 남지 않게 덮어쓰기로 이동. 알고리즘 수행 후 순차열은 [b,p)가 됨
p=unique(b,e,t) 구간 [b,e) 순차열에서 인접한 중복 원소가 아닌 원소를 순차열 [t,p)에 복사
p=unique(b,e,t,f) 구간 [b,e)의 순차열에서 f(*p)가 참인 인접한 중복 원소가 아닌 원소를 순차열 [t,p)에 복사

2. 상세 예시

  1. remove(b,e,x)
    • 구간 [b,e) 순차열에서 x인 원소가 남지 않게 함
vector<int> v = {10,20,30,40,50};
auto iter = remove(v.begin(), v.end(), 30);
// v => 10,20,40,50,50
// iter - 1 => 첫번째 50을 가리킴
// 실제로 [v.begin,iter)는 10,20,40,50 이 됨
  1. remove_if(b,e,f)
    • 구간 [b,e) 순차열에서 f(*p) 가 참인 원소가 남지 않게 함
bool Pred(int n){
   return 30 <= n && n <= 40;
} // 30~40 인 원소만 참

vector<int> v = {10,20,30,40,50};

auto iter = remove_if(v.begin(), v.end(), Pred);
// v => 10,20,50,40,50
// iter - 1 => 첫번째 50을 가리킴
  1. remove_copy(b,e,t,x)
    • 순차열의 원본을 변경하지 않고 특정 원소를 제거하여 목적지 순차열에 복사
vector<int> v1 = {10,20,30,40,50};
vector<int> v2(5);
auto iter = remove_copy(v1.begin(), v1.end(), v2.begin(), 30);
// v1에서 30을 제거하고 v2에 복사
// v2 = {10,20,40,50,0}
// iter -1 => 50을 가리킴
  1. unique(b,e)
    • 구간 [b,e)의 순차열을 인접한 중복 원소가 남지 않게 함
    • 원소를 삭제하지 않고 논리적으로만 제거
vector<int> v = {10,20,30,30,40,40,30,50};
auto iter = unique(v.begin(), v.end());
// v = {10,20,30,40,30,50,30,50}
// iter -1 => 첫 번째 50을 가리킴
// [v.begin(), iter) = {10,20,30,40,30,50}
  1. unique(b,e,f)
    • 인접한 원소를 인자로 받은 이항 함수 f를 사용
    • 구간 [b,e) 의 인접한 원소의 함수 f가 참인 원소를 제거
bool Pred(int left, int right){
   return abs(right-left) < 10;
}// 인접한 원소 차이가 10 미만이면 삭제

vector<int> v = {10,11,30,32,40,50};

auto iter = unique(v.begin(), v.end(), Pred);
// v => {10,30,40,50,40,50}
// iter - 1 => 첫 번째 50을 가리킴
// [v.begin(), iter) => {10,30,40,50}

참고

뇌를 자극하는 C++ STL

반응형
반응형

1. 원소를 수정하는 알고리즘 리스트

알고리즘 설명
p=copy(b,e,t) 구간 [b,e)의 원소를 [t,p)로 모두 복사
p=copy_backward(b,e,t) 구간 [b,e)의 원소를 마지막 원소부터 [p,t)로 모두 복사
fill(b,e,x) 구간 [b,e)의 모든 원소를 x로 채움.
fill_n(b,n,x) 구간 [b,b+n)의 모든 원소를 x로 채움.
f=for_each(b,e,f) 구간 [b,e)의 모든 원소에 f(*p) 동작을 적용한다. f를 다시 되돌려 줌
generate(b,e,f) 구간 [b,e)의 모든 원소를 f()로 채움
generate_n(b,e,f) 구간 [b,b+n)의 모든 원소를 f()로 채움
iter_swap(p,q) 반복자 p, q가 가리키는 *p와 *q의 원소를 교환
p=merge(b,e,b2,e2,t) 정렬된 순차열 [b,e)와 [b2,e2)를 [t,p)로 합병 정렬
p=merge(b,e,b2,e2,t,f) 정렬된 순차열 [b,e)와 [b2,e2)를 [t,p)로 합병 정렬. 이때 비교는 f를 사용
replace(b,e,x,x2) 구간 [b,e)의 x인 원소를 x2로 수정
replace_if(b,e,f,x2) 구간 [b,e)의 f(*p)가 참인 원소를 x2로 수정
p=replace_copy(b,e,t,x,x2) 구간 [b,e)의 x인 원소를 x2로 수정하여 [t,p)로 복사
p=replace _copy_if(b,e,t,f,x2) 구간 [b,e)의 f(*p)가 참인 원소를 x2로 수정하여 [t,p)로 복사
swap(a,b) a와 b를 교환
swap_ranges(b,e,b2) 구간 [b,e)의 원소와 구간 [b2, b2+(e-b))의 원소를 교환
p=transform(b,e,t,f) 구간 [b,e)의 모든 원소를 f(*p)하여 [t, t+(e-b))에 저장. p는 저장된 마지막 원소의 반복자 (t+(e-b)) 임
p=transform(b,e,b2,t,f) 구간 [b,e)와 [b2, b2+(e-b))의 두 순차열의 반복자 p,q일 때 모든 원소를 f(*p, *q) 하여 [t,t+(e-b))에 저장. p는저장된 마지막 원소의 반복자(t+(e-b)) 임

2. 예시

  1. copy()
vector<int> v1 = {10,20,30,40,50};
vector<int> v2(5);

auto iter = copy(v1.begin(), v1.end(), v2.end());
// v2에 v1의 값을 복사
// iter - 1 이 50을 가리킴
  1. copy_backward()
    • v2의 마지막 위치 부터 데이터를 복사함
vector<int> v1 = {10,20,30,40,50};
vector<int> v2(10);

auto iter = copy_backward(v1.begin(), v1.end(), v2.end());
// v2 = 0, 0, 0, 0, 0, 10, 20, 30, 40, 50
// iter 는 10의 위치 가리킴
  1. fill , fill_n
    • fill : 구간 [begin, end) 를 x로 채움
    • fill_n : begin부터 n개 개수만큼 x로 채움
vector<int> v = {10,20,30,40,50};
fill(v.begin(), v.end(), 0);
// v를 0으로 채움
fill_n(v.begin(), 3, 55);
// v.begin 부터 3개 만큼을 55로 채움
  1. for_each()
    • functor의 인자를 &로 줘서 값 변경 가능
void Func(int& r){
   r += 5;
}  // 원소값에 5를 더함

vector<int> v = {10,20,30,40,50};

for_each(v.begin(), v.end(), Func);
// v의 모든 원소에 5를 더함
  1. generate, generate_n
    • 순차열의 모든 원소를 단순한 동작의 값으로 수정
    • for_each와의 차이 => 함수의 매개변수로 순차열의 원소를 전달하지 않음
    • generate(b,e,f) : 구간[b,e)의 모든 원소를 f()로 채움
    • generate(b,n,f) : b부터 n개 만큼 원소를 f()로 채움
class Integer{
   int data;
public:
   explicit Integer(int d= 0) : data(d) {}
   int operator()(){
      return data++;
   }
};

vector<int> v = {10,20,30,40,50};

generate(v.begin(), v.end(), Integer(1));
// v를 1,2,3,4,5 로 채움

generate_n(v.begin(), 3, Interger(100));
// v 의 시작부터 3개까지 원소를 100, 101, 102로 채움
  1. swap , iter_swap

    • swap(a, b) : a와 b를 교환
    • iter_swap(p,q) : iter p와 q의 값을 교환
  2. merge(b,e,b2,e2,t)

    • 정렬된 구간 [b,e) 와 [b2,e2)를 합병 정렬
    • 결과는 [t,t+(e-b)+(e2-b2))의 순차열
    • 반드시 정렬되어 있어야 가능함
    • default는 less(오름차순 정렬)
vector<int> v1 = {10,30,50,60,80};
vector<int> v2 = {20,40,70};
vector<int> v3(10);
iter = merge(v1.begin(), v1.end(), v2.begin(), v2.end(), v3.begin());
//v3 = 10,20,30,40,50,60,70,80,0,0
//iter -1 => 80을 가리킴
  1. merge(b,e,b2,e2,t,f)
    • f는 [b,e), [b2,e2)의 정렬 기준
template<typename T>
struct Greater{
   bool operator()(const T& left, const T& right) const{
      return left > right;
   }
};

vector<int> v1 = {80,60,50,30,10};
vector<int> v2 = {70,40,20};
vector<int> v3(10);

iter = merge(v1.begin(), v1.end(), v2.begin(), v2.end(), v3.begin(), Greater<int>());
// v3 = 80,70,60,50,40,30,20,10,0,0
// iter - 1 => 10 가리킴
  1. replace(b,e,x,x2)
    • 순차열의 특정 원소를 다른 값으로 수정
    • [b,e)구간의 x인 원소를 x2로 수정
vector<int> v = {10,20,30,40,30,30,50};

replace(v.begin(), v.end(), 30, 0);
// v 모든 원소 중 30을 0으로 변경
// v = {10,20,0,40,0,0,50};
  1. replace_if(b,e,f,x2)

    • [b,e) 구간에서 f(*p)가 참인 원소를 x2로 변경
bool Pred(int n){
   return 30 <= n && n <= 50;
} // n이 30~50 인 경우 true

vector<int> v = {10,20,30,40,50,60,70,80};

replace_if(v.begin(), v.end(), Pred, 0);
// v의 모든 원소 중 Pred가 참인 원소를 0으로 변경
// v = {10,20,0,0,0,60,70,80}
  1. replace _copy, replace _copy_if
    • replace_copy(b,e,t,x,x2) : 구간 [b,e)에서 x를 x2로 변경 후 [t,p)로 복사
    • replace _copy_if(b,e,t,f,x2) : 구간 [b,e)에서 f가 참인 원소를 x2로 변경 후 [t,p)로 복사
bool Pred(int n){
   return n <= 30;
} // 30보다 작으면 참

vector<int> v1 = {10,20,30,40,30,50};
vector<int> v2(6);
vector<int> v3(6);

auto iter = replace_copy(v1.begin(), v1.end(), v2.begin(), 30, 0);
// v1의 모든 원소에서 30인 원소를 0으로 변환하여 [v2.begin(), iter) 에 저장

iter = replace_copy_if(v1.begin(), v1.end(), v3.begin(), Pred, 0);
// v1의 모든 원소에서 Pred가 참인 원소를 0으로 변환하여 [v3.begin(), iter) 에 저장
  1. swap_ranges(b,e,b2)
    • 구간 [b,e)의 순차열과 [b2,b2+e-b)의 모든 원소를 교환
vector<int> v1 = {10,20,30,40,50};
vector<int> v2 = {11,22,33,44,55};

swap_ranges(v1.begin(), v1.end(), v2.begin());
// v1의 모든 원소와 v2의 원소를 교환
// v1 = {11,22,33,44,55}
// v2 = {10,20,30,40,50}
  1. transform(b,e,t,f)
    • for_each()와의 차이점 => 원본의 순차열 변화 없이 목적지의 순차열로 저장
    • 구간 [b,e) 의 원소를 인자로 하는 함수 f를 호출
    • 반환값을 순차열 [t, t+(e-b))로 저장
int Func(int n){
   return n+5;
} // n에 5를 더함

vector<int> v = {10,20,30,40,50};
auto iter = transform(v.begin(), v.end(), v.begin(), Func);
// v의 모든 원소에 5를 더함
// v => {15,25,35,45,55}
// iter - 1 => 50을 가리킴
  1. transform(b,e,b2,t,f)
    • 두 순차열의 원소에 함수 적용
    • 구간 [b-e) 와 [b2, b2+(e-b))의 순차열 반복자를 함수 f에 인자로 전달
    • 그 결과를 순차열[t, t+(e-b))에 저장
int Plus(int left, int right){
   return left+right;
}// left와 right를 더하는 함수

vector<int> v1 = {10,20,30,40,50};
vector<int> v2 = {1,2,3,4,5};
vector<int> v3(5);

auto iter = transform(v1.begin(), v1.end(), v2.begin(), v3.begin(), Plus);
// v1와 v2의 원소를 더해서 v3에 저장
// v3 => {11,22,33,44,55}
// iter - 1 => 55의 위치를 가리킴

참고

뇌를 자극하는 C++ STL

반응형
반응형

1. 원소를 수정하지 않는 알고리즘 리스트

알고리즘 설명
p=adjacent_find(b,e) p는 구간 [b,e) 원소 중 *p == *(p+1)인 첫 원소를 가리키는 반복자
p=adjacent_find(b,e,f) p는 구간 [b,e) 원소 중 f(*p, *(p+1))이 참인 첫 원소를 가리키는 반복자
n=count(b,e,x) n은 구간 [b,e)의 원소 중 x의 개수
n = count_if(b,e,f) n은 구간[b,e)의 원소 중 f(*p) 가 참인 원소 개수
equal(b,e,b2) [b,e) 와 [b2, b2+(e-b))의 모든 원소가 같은가?
equal(b,e,b2,f) [b,e) 와 [b2, b2+(e-b))의 모든 원소가 f(*p, *q)가 참인가?
p=find(b,e,x) p는 구간 [b,e)에서 x와 같은 첫 원소의 반복자
p=find_end(b,e,b2,e2) p는 구간 [b,e)의 순차열 중 구간[b2,e2)의 순차열과 일치하는 순차열 첫 원소의 반복자. 단 [b2,e2)와 일치하는 순차열이 여러 개 라면 마지막 순차열 첫 원소의 반복자
p=find_end(b,e,b2,e2,f) p는 구간 [b,e)의 순차열 중 구간[b2,e2)의 순차열과 일치하는 순차열 첫 원소의 반복자. 단 [b2,e2)와 일치하는 순차열이 여러 개 라면 마지막 순차열 첫 원소의 반복자. 이 때 비교는 f를 사용
p=find _first_of(b,e,b2,e2) p는 구간 [b,e)에서 구간 [b2, e2)의 원소 중 가은 원소가 발견된 첫 원소의 반복자
p=find _first_of(b,e,b2,e2,f) p는 구간 [b,e)에서 구간 [b2,e2)의 원소 중 같은 원소가 발견된 첫 원소의 반복자. 이때 비교는 f를 사용
p=find_if(b,e,f) p는 구간[b,e)에 f(*p)가 참인 원소를 가리키는 반복자
f=for_each(b,e,f) 구간 [b,e)의 모든 원소에 f(*p) 동작을 적용한다. f를 다시 되돌려 준다.
lexicographical_compare(b,e,b2,e2) 구간 [b,e)의 순차열이 구간 [b2,e2)의 순차열보다 작다면 true, 아니면 false를 반환
lexicographical_compare(b,e,b2,e2,f) 구간 [b,e)의 순차열이 구간 [b2,e2)의 순차열보다 작다면 true, 아니면 false를 반환한다. 이때 작음은 [b,e)의 반복자 p와 [b2,e2)의 반복자 q에 대해 f(*p, *q)가 참이다.
k=max(a,b) k는 a와 b 중 더 큰 것
k=max(a,b,f) k는 a와 b 중 더 큰 것. 이때 큰 것은 f(a,b)를 사용
p=max_element(b,e) p는 구간 [b,e)에서 가장 큰 원소의 반복자
p=max_element(b,e,f) p는 구간 [b,e)에서 가장 큰 원소의 반복자. 이때 비교는 f를 사용
k=min(a,b) k는 a와 b중 더 작은 것
k=min(a,b,f) k는 a와 b 중 더 작은 것. 이때 작은 것은 f(a,b)를 사용
p=min_element(b,e) p는 구간 [b,e)에서 가장 작은 원소의 반복자
p=jmin_element(b,e,f) p는 구간 [b,e)에서 가장 작은 원소의 반복자. 이때 비교는 f를 사용
pair(p,q)=mismatch(b,e,b2) (p,q)는 구간 [b,e)와 [b2,b2+(e-b))에서 !(p=q)인 첫 원소를 가리키는 반복자의 쌍
pair(p,q)=mismatch(b,e,b2,f) (p,q)는 구간 [b,e)와 [b2,b2+(e-b))에서 !f(p,q)가 참인 첫 원소를 가리키는 반복자의 쌍
p=search(b,e,b2,e2) p는 구간 [b,e)의 순차열 중 구간 [b2,e2)의 순차열과 일치하는 순차열 첫 원소의 반복자(find_end()와 비슷하나 find_end()는 일치하는 순차열의 마지막 순차열의 반복자)
p=search(b,e,b2,e2,f) p는 구간 [b,e)와 순차열 중 구간 [b2,e2)의 순차열과 일치하는 순차열의 첫 원소의 반복자. 이때 비교는 f를 사용
p=search_n(b,e,n,x) p는 구간 [b,e)의 원소 중 x 값이 n개 연속한 첫 원소의 반복자
p=search_n(b,e,n,x,f) p는 구간 [b,e)의 원소 중 f(*p,x)가 참인 값이 n개 연속한 첫 원소의 반복자

2. 범위 내에 순차열 포함 여부 찾기

  1. iter = find_end(v1.begin(), v1.end(), v2.begin(), v2.end())
    • v1의 [begin,end) 범위에서 v2의 [begin,end) 순차열을 포함하는 제일 마지막 반복자 반환
vector<int> v1 = {30,40,10,30,40};
vector<int> v2 = {30,40};

iter = find_end(v1.begin(), v1.end(), v2.begin(), v2.end());
// iter는 30의 두번째 위치를 반환

iter = search(v1.begin(), v1.end(), v2.begin(), v2.end());
// iter는 30의 첫번째 위치를 반환
  1. iter = search(v1.begin(), v1.end(), v2.begin(), v2.end())

    • 위와 동일하지만 처음에 위치한 30의 위치 반환
  2. iter = find_end(v1,begin(), v2.end(), v2.begin(), v2.end(), Pred)

    • Pred : d이항 함수(인자가 두개)
    • 범위 내에 비교하여 Pred함수가 모두 참인 구간 중 마지막 구간의 첫 원소의 위치를 반환
  3. iter = search_n(v,begin(), v.end(), 3, 30)

    • [v.begin(), v.end()) 에서 30이 3번 연속한 첫 원소의 반복자 반환
  4. iter = find _first_of(v1.begin(), v1.end(), v2.begin(), v2.end())

    • v1의 구간 [begin, end) 순차열에서 v2의 구간 [begin,end) 원소 중 같은 원소가 처음으로 발견되는 첫 원소의 반복자 반환
vector<int> v1 = {10,20,30,40,50};
vector<int> v2 = {40,80,20};

iter = find_first_of(v1.begin(), v1.end(), v2.begin(), v2.end())
// 20의 위치를 반환
  1. iter = find _first_of(v1.begin(), v1.end(), v2.begin(), v2.end(), Pred)
    • Pred : 이항 연산자
    • Pred 함수가 청므으로 참이 나오는 위치 반환
bool Pred(int left, int right){
   return left > right;
} // 왼쪽 요소가 오른쪽 요소보다 크면 참

vector<int> v1 = {10,20,30,40,50};
vector<int> v2 = {40,80,20};

iter = find_first_of(v1.begin(), v1.end(), v2.begin(), v2.end(), Pred)
// 30이 처음으로 20보다 크모 30 위치 반환
// 10 < 40, 20 < 80, 30 >20

3. 기타

  1. iter=adjacent(v.begin(),v.end())
    • v의 연속된 원소가 같아지는 첫 원소의 반복자 반환
    • 10,20,30,30인 경우 첫 30의 반복자 반환
    • 못찾으면 v.end()를 반환
    • 이항 조건자를 인자로 줘서 여러 조건으로 판단 가능
bool Pred(int a, int b){
   return abs(b-e) > 10;
} // 연속된 두 수의 절대값이 10보다 크면 참

iter = adjacent_find(v.begin(), v.end(), Pred)
// Pred 함수가 처음으로 참인 반복자 반환
  1. int n = count(v.begin(), v.end(), 30)

    • [v.begin(),v.end()) 범위에서 30의 개수 리턴
  2. int n = count_if(v.begin(), v.end(), Pred)

    • [v.begin(),v.end()) 범위에서 Pred 함수가 참인 개수 리턴
  3. equal(v1.begin(),v1.end(),v2.begin())

    • v1의 begin~end 범위의 데이터가 v2와 같으면 참
  4. eqaul(v1.begin(),v1.end(),v2.begin(),Pred)

    • v1의 begin~end 범위의 데이터와 v2의 데이터가 Pred 함수 인자로 들어가서 모두 참이면 참
bool Pred(int left, int right){
   return abs(right-left) < 5;
} // 두 원소의 차이가 5보다 작으면 참

vector<int> v1 = {10,21,30};
vector<int> v2 = {10,20,33};

bool b = equal(v1.begin(), v1.end(), v2.begin(), Pred)
// b는 true
  1. for_each(v.begin(), v.end(), Print)
    • Print : 요소와 같은 형태의 인자를 가지는 단항 함수
    • v의 [begin,end) 범위의 요소를 Print 함수에 전달하여 함수 수행
    • 함수 객체를 전달하면 다양한 형태로 사용 가능
struct PrintFunctor{
   char fmt;
   explicit PrintFunctor(char c='') : fmt(c){}
   void operator()(int n)const {
      cout<<n<<fmt;
   }
}

for_each(v.begin(), v.end(), PrintFunctor());
// 원소 구분을 ''로 하여 출력
for_each(v.begin(), v.end(), PrintFunctor(,));
// 원소 구분을 ,로 하여 출력
  1. 순차열 사전순 비교

    • lexicographical_compare(v1.begin(), v1.end(), v2.begin(), v2.end())
      • v1과 v2의 순차열 비교하여 v2가 크면 true 반환
      • ex) v1 = [10,20,30], c2=[10,20,50] => true 반환
    • greater() 를 인자로 추가하여 비교 기준 변경
  2. max(pt1, pt2, XCompare)

    • Xcompare는 Point의 x좌표를 비교하는 이항 함수
    • Point 객체의 x좌표를 비교해 큰 객체 반환
  3. iter = max_element(v.begin(), v.end())

    • v의 구간 [begin,end)에서 max값의 위치 반환
  4. iter = min_element(v.begin(), v.end())

    • v의 구간 [begin,end)에서 min값의 위치 반환
  5. iter = max_element(v.begin(), v.end(), Comp)

    • 벡터의 원소가 객체일 경우 비교 방법 Com 함수(이항 함수) 정의
  6. iter_p = mismatch(v1.begin(), v1.end(), v2.begin())

    • v1과 v2의 원소가 다른 첫 위치를 반환
    • 반환값은 v1과 v2의 위치를 담은 pair 객체

참고

뇌를 자극하는 C++ STL

반응형
반응형

0. 연관 컨테이너

  1. 모든 연관 컨테이너는 노드 기반 컨테이너
  2. 모든 연관 컨테이너는 균형 이진 트리
  3. 모든 연관 컨테이너는 같은 인터페이스 제공
  4. 찾기 연산에 뛰어난 성능을 보임(로그 시간)
  5. 삽입 또한 로그 시간 복잡도
  6. 기본 정렬은 less(오름차순 정렬)
  7. 종류
    • set : key값의 집합, 중복 허용 안함
    • multiset : set인데 중복 허용
    • map : key, value쌍의 집합, 중복 허용 안함
    • multimap : map인데 중복된 key값 허용

1. set 컨테이너

  1. key값의 집합을 가지는 컨테이너
  2. 템플릿 형식
template<typename key,
         typename Pred=less<Key>,
         typename Allocator=allocator<Key>
>
class set
  1. 생성자

    코드 내용
    set s s는 빈 컨테이너
    set s(pred) s는 빈 컨테이너로 정렬 기준은 pred 조건자 사용
    set s(s2) s는 s2 컨테이너의 복사본(복사 생성자 호출)
    set s(b,e) s는 반복자 구간 [b,e)로 초기화된 원소 가짐
    set s(b,e,Pred) s는 반복자 구간[b,e)로 초기화된 원소 가짐(정렬 기준은 pred 조건자 사용)
  2. 멤버 함수

    코드 내용
    p=s.begin() p는 s의 첫원소를 가리키는 반복자
    p=s.end() p는 s의 끝을 나타내는 반복자
    s.clear() s의 모든 원소 제거
    s.empty() s가 비었는지 조사
    n=s.count(k) 원소 k의 개수 반환
    pr=s.equal_range(k) pr은 k 원소의 반복자 구간인 pair 객체
    q=s.erase(p) p가 가리키는 원소 제거(q는 다음 원소 가리킴)
    q=s.erase(b,e) 반복자 구간[b,e)의 모든 원소를 제거(q는 다음 원소)
    n=s.erase(k) k 원소를 모두 제거, n은 제거 개수
    pr=s.insert(k) s 컨테이너에 k 삽입. pr은 삽입한 원소를 가리키는 반복자와 성공 여부의 bool값인 pair 객체
    q=s.insert(p,k) p가 가리키는 위치부터 빠르게 k를 삽입. q는 삽인한 원소를 가리킴
    s.insert(b,e) 반복자 구간[b,e)의 원소를 삽입
    pred=s.key_comp() s의 key 정렬 기준인 조건자 반환(pred)
    pred=s.value_comp() s의 value 정렬 기준인 조건자 반환(pred)
    p=s.lower_bound(k) p는 k의 시작 구간을 나타내는 반복자
    p=s.upper_bound(k) p는 k의 끝 구간을 가리키는 반복자
    n=s.max_size() n는 s가 담을 수 있는 최대 원소 개수(메모리 크기)
    p=s.rbegin() p는 s의 역 순차열의 첫 원소를 가리키는 반복자
    p=s.rend() p는 s의 역 순차열의 끝을 표식하는 반복자
    s.size() s 원소의 개수
    s.swap(s2) s와 s2를 swap
  3. 연산자

    코드 내용
    s1==s2 s1과 s2의 모든 원소가 같은가?
    s1!=s2 s1과 s2의 원소중 하나라도 다른가?
    s1 < s2 문자열 비교처럼 s2가 s1보다 큰가?
  4. 멤버 형식

    코드 내용
    allocator_type 메모리 관리자 형식
    const_iterator const 반복자 형식
    const_pointer const value_type* 형식
    const_reference const value_type& 형식
    const _reverse_iterator const 역 반복자 형식
    difference_type 두 반복자 차이의 형식
    iterator 반복자 형식
    key_compare 키 조건자 형식
    key_type key의 형식
    pointer value_type* 형식
    reference value_type& 형식
    reverse_iterator 역 반복자 형식
    size_type 첨자(index)나 원소의 개수 등의 형식
    value_compare 원소 조건자 형식
    value_type 원소의 형식

2 상세 내용

  1. 원소 추가는 insert() 만 제공
    • push _back() , pop_front() 등의 함수 제공 안함
    • 반환값은 pair객체이면 first는 키의 위치를 가리키는 반복자
    • second 는 성공 실패를 나타내는 bool
    • 중복값이 있을 경우 second의 false 리턴
    • 예제
set<int> s;
pair<set<int>::iterator, bool> pr;
pr = s.insert(50);
// pr.first : 50이 삽입된 위치를 가리키는 반복자
// pr.second : true
pr = s.insert(50);
// pr.first : 존재하는 50의 위치를 가리키는 반복자
//pr.second : false
  1. s.insert(pr.first, 85)

    • pr.first 위치부터 탐색 시작하여 85 삽입
  2. set<int, greater<int>> s

    • 정렬 기준을 greater(내림차순)으로 s 생성
  3. set의 조건자 반환(정렬 기준 함수 객체)

    • key_compare : 정렬 기준 함수를 담는 형식
    • key_comp() : set의 정렬 기준 함수 반환
set<int, less<int>> s_less;
set<int, less<int>>::key_compare l_cmp = s_less.key_comp();
  1. s.count(50)

    • 50의 원소 개수 반환
    • set은 중복 허용 안하므로 1개
  2. s.find(30)

    • 30을 찾아 반복자 반환
    • 찾는게 없으면 s.end() 반환
    • s.find(30) != s.end() 이면 찾은 것!
  3. find 원리

    • 정렬 기준 조건자를 이용
if(s.key_comp()(a,b)) && !(s.key_comp()(b,a))
// 위의 조건이 참이면 두 원소는 같다고 판단함
// 정렬 기준으로 a가 b보다 앞서있지 않고,
// b도 a보다 앞서 있지 않다면 같다고 판단
  1. 구간 반복자
    • lower_bound(k) : k의 시작 구간
    • upper_bound(k) : k의 끝 구간
    • equal_range(k) : lower, upper 를 가지는 pair
set<int> s = {10, 30, 40, 50, 70};
iter_lower = s.lower_bound(30);
// => 30을 가리킴
iter_upper = s.upper_bound(30)
// => 40을 가리킴
iter_lower = s.lower_bound(55);
// => 70을 가리킴
iter_upper = s.upper_bound(55);
// => 70을 가리킴

if (iter_lower == iter_upper)
   //찾는 원소 없음

s.equal_range(30)
// lower 와 upper 반복자를 pair 객체로 반환

3. multiset 컨테이너

  1. set과의 차이점
    • 중복 원소를 허용
  2. ms.count(30)
    • 원소 30의 개수(중복 허용)
  3. ms.find(30)
    • 원소 30의 첫 위치(중복일 경우)
  4. lower _iter = ms.lower_bound(30)
    • 원소 30이 시작되는 위치
  5. upper _iter = ms.uppter_bound(30)
    • 원소 30의 끝 다음 위치
    • 30, 30, 50 의 경우 50

4. map 컨테이너

  1. set과의 차이점
    • key, value 쌍(pair)으로 객체 저장
  2. m.insert(pair<int, int>(5,100))
    • key : 5, value : 100을 가지는 원소 추가
    • 반복자와 성공여부를 가지는 pair 리턴
  3. m[5] = 100
    • 키값 5가 없으면 100 추가, 있으면 값을 100으로 업데이트
  4. m.find(5)
    • key값 5를 찾아 그 위치 반복자 반환
    • 반복자가 m.end()이면 key값 없음

5. multimap 컨테이너

  1. map과의 차이점
    • 중복된 key값을 허용

참고

뇌를 자극하는 C++ STL

반응형

+ Recent posts

반응형