본문 바로가기

C++

[TIL 30장] 벡터 함수(feat. 2차원벡터), 알고리즘(feat. 조건자)

오늘의 TIL 목차 (22. 09. 17)

 

  • 벡터 함수
  • 알고리즘(feat. 조건자)

벡터 함수


[ 벡터 함수 ]

: 컨테이너 벡터에서만 사용되는 함수

@. vector<T> vec(10); 0으로 초기화된 메모리 공간 10개 생성;
@. vector<T> vec(10,1): 1로 초기화된 메모리 공간 10개 생성;
@. reserve(숫자); : 숫자만큼 메모리 용량을 늘려 재할당하는 함수, 현재 메모리 용량보다 숫자가 더 클 때만 동작
@. resize(숫자) : 원소를 숫자만큼만 유지하고 뒤의 원소는 전부 삭제하는 함수, 메모리 공간은 유지

 

void main(void)
{
	vector<int> vec;
	vector<int>::iterator iter;
	
	for (size_t i = 0; 5 > i; ++i)
	{
		vec.push_back(i + 1);
		cout << "원소 개수 : " << vec.size() << "\t 용량 : " << vec.capacity() << endl;
	}

	cout << "원소 : ";
	for (iter = vec.begin(); vec.end() != iter; ++iter) // Iterator가 ++연산자 오버로딩에 의해 반복되는 거라, 안의 int형은 반복문이 돌아도 증가하지 않음!
		cout << (*iter) << "\t";

	cout << endl;
	cout << "reserve 전 용량 : " << vec.capacity() << endl;
	vec.reserve(20); // 메모리 용량 20짜리 배열 재할당 (현재 메모리 공간보다 크게만 할당 가능)
	cout << "reserve(20) 후 용량 : " << vec.capacity() << endl;
	vec.resize(2); // 원소 2개, [0] [1]만 남겨두고 뒤의 원소 삭제
	cout << "resize(2) 후 vec.back() : " << vec.back() << "\t 용량 :" << vec.capacity() << endl;
}

출력 결과

 

알고리즘


[ 알고리즘 ]

: 어떤 일을 해결하기 위한 방법이나 문제를 해결하기 위한 절차 등을 단계적으로 나열한 것

: STL에서 알고리즘은 편의성을 위해 자료구조를 기반으로 한 함수 템플릿을 제공한다.

#include <algorithm> // 알고리즘 사용 시 헤더파일 포함
- 함수명 ( begin, end, 조건자 ); // 알고리즘 형태, begin , end(마지막 원소의 다음 위치) 는 Iterator / 주소 

* 조건자 위치에는 함수, 함수객체, 람다식이 온다.
* sort 등의 조건자가 쓰이는 함수들은 조건자에 자동으로 매개변수가 들어가므로 조건자 함수에는 ()를 생략한다.
* 조건자는 전역이거나 static이 붙어있는 함수 또는 함수객체(함수포인터도 가능)이여야 한다.
=> 알고리즘 함수에 따라 알아서 조건자의 매개변수에 들어가기 때문

@. sort(begin, end, (조건자) ); 
: 퀵 기반으로 짜여진 "정렬" 함수 ( (조건자 없으면 디폴트) 오름차순 )
- 시퀀스 컨테이너만 보유 ( 연관 컨테이너는 자동 정렬하기 때문에 정렬이 필요없음 )
- '리스트'만 예외적으로 sort 멤버 함수를 보유 (알고리즘X) ( 리스트는 노드 기반이지만 시퀀스 )

@. count_if(begin, end, 조건자 ); 
: 컨테이너 원소를 순회하면서 매개변수로 넘겨받은 조건자의 반환 결과가 참인 개수를 반환하는 템플릿

@. for_each(begin, end, 조건자); // for문의 기능을 하는 함수
: 물려받은 원소를 조건자(함수, 함수 객체)의 형식으로 반환하는 함수 템플릿

 

[ 조건자 ]

: 알고리즘 함수의 조건 부분으로, 주로 조건자를 기준으로 알고리즘이 실행된다.

#include <algorithm>

sort( begin, end, (조건자))
- 조건자 생략 시 default는 오름차순 정렬
- 조건자는 begin과 end, 2개의 매개변수를 받아 조건식을 돌림
- 주로 bool 타입을 반환하여 true, false에 따라 정렬

count_if( begin, end, 조건자 )
- 조건자는 begin부터 end까지 순회하는 하나의 매개변수를 받음
- 조건자는 '무조건' bool 타입을 반환해야 함
- count_if는 조건자를 통해 참의 개수를 반환하는 함수이기 때문

for_each( begin, end, 조건자 ) - for문처럼 쓰이며 원소에 접근함
- 반드시 조건자에 함수 객체가 와야 한다. ( 함수 포인터 X )
- 함수 객체를 이용한 inline화?

find_if( begin, end, 조건자 )
- 매개변수 하나 받음
- 존재하지 않으면 end 반환?
- 조건자와 일치하면 해당 반복자를, 없으면 end를 반환

-

[ sort 조건자에 들어갈 간편 Functor ]
#include <Functional> // 포함해야 사용 가능

@. greater<자료형>() : 내림차순 >
@. less<자료형>() : 오름차순 <

■ 기능 / 주의

  • 조건자의 함수 객체 또는 함수는 ()를 쓰지 않는다, 임시 객체로 넣을 경우 생성자 호출을 위해 ()를 쓴다.
    - 조건자는 알고리즘의 begin, end에 의해 자동으로 매개변수가 들어가기 때문에 () 안 씀
  • 조건자는 전역변수 또는 클래스 내부일 경우 static 변수여야 한다. ( 알고리즘 전체 기준이 되야 하기 때문 )
  • 조건자의 매개변수 타입은 "원소의 타입"이어야 한다. ( iterator 아님 )
    - 알고리즘의 begin, end 위치에는 iterator나 주소로 보내준다.
  • 조건자는 꼭 알고리즘의 조건자로 쓰일 필요는 없다. 일반적인 함수, 함수객체로써 사용 가능
  • Functional 헤더 파일에 들어있는 greater<>() 등을 이용하여 조건자 넣어주기 가능
    - greater<>()는 임시 객체를 생성하는 것으로, 오름차순 기능을 하여 조건자 용도로 사용됨
    - less<>()는 내림차순 기능을 하는 functor

■ 예시

#include "stdafx.h"
#include <algorithm>
// 조건자는 전역에 선언 ( 또는 static ) 

// 함수ver
bool Down_Number(int _iA, int _iB)
{
	return _iA > _iB; // begin 원소가 크면 참을 반환, 내림차순
}

// 템플릿 함수ver
template<typename T>
bool		IsOddNum(T Number)
{
	if (0 != Number % 2)
		return true;

	return false;
}

// 함수 객체ver
class Functor
{
	bool operator()(auto A)
    {
    	return true;
    }
}

void main(void)
{
	srand(unsigned int(time(nullptr))); // 실시간으로 변하는 수 
	vector<int> vecInt;

	for (size_t i = 0; 5 > i; ++i)
	{
		vecInt.push_back(rand() % 10);
		cout << vecInt[i] << "\t"; // 벡터는 대괄호 연산자 가능 ( operator[]가 있기 때문 )
	}
	cout << endl;
	
	vector<int>::iterator iter = vecInt.begin();
    
	sort(vecInt.begin(), vecInt.end()); // 조건자는 default에 의해 오름차순 정렬
    - 출력 생략 -
    sort(vecInt.begin(), vecInt.end(), Down_Number); // 내림차순 기능의 함수로 인해 내림차순
    - 출력 생략 =
   // count_if는 조건자를 통해 true 개수를 반환해주므로 반환값을 iNum으로 받아주기 (아니면 소멸됨)
	int iNum = count_if(vecInt.begin(), vecInt.end(), IsOddNum<int>); // 함수, 함수 객체 () 사용 X
	cout << iNum << "개 ( 홀수)" << endl;
    
    /* 출력 부분
	for (iter = vecInt.begin(); vecInt.end() != iter ; ++iter)
	{
		cout << (*iter) << "\t";
	}
    */
}

-

출력결과:
4	3	6	3	0 // rand()%10 값 벡터에 push
0	3	3	4	6 // 오름차순 정렬
6	4	3	3	0 // 내림차순 정렬
3개 // count_if의 홀수 참 반환 조건자를 통한 홀수 개수, 0은 홀수 X