오븐 노트

[C++] algorithm 본문

Develop/C++

[C++] algorithm

오 븐 2023. 9. 30. 18:53
#include <iostream>
using namespace std;
#include <vector>
#include <list>
#include <deque>
#include <map>
#include <set>
#include <algorithm>

int main()
{
    // 자료구조 (데이터를 저장하는 구조)
    // 알고리즘 (데이터를 어떻게 사용할 것인가?)

    // 현업에서 많이 사용하는 알고리즘
    // find
    // find_if
    // count
    // count_if
    // all_of
    // any_of
    // none_of
    // for_each
    // remove
    // remove_if

    srand(static_cast<unsigned int>(time(nullptr)));

    vector<int> v;

    for (int i = 0; i < 100; i++)
    {
        int num = rand() % 100;
        v.push_back(num);
    }

    // Q1) number라는 숫자가 벡터에 체크하는 기능 (bool, 첫 등장 iterator)
    {
        int number = 50;

        bool found = false;
        vector<int>::iterator it = v.end(); // iterator 선언을 auto로 생략 가능

        // TODO
        for (unsigned int i = 0; i < v.size(); i++)
        {
            int data = v[i];

            if (data == number)
            {
                found = true;
                it = v.begin() + i;
                break;
            }
        }

        vector<int>::iterator itFind = find(v.begin(), v.end(), number); // iterator 선언을 auto로 생략 가능
        if (itFind == v.end())
        {
            cout << "실패" << endl;
        }
        else
        {
            cout << "성공" << endl;
        }
    }

    // Q2) 11로 나뉘는 숫자가 벡터에 있는지 체크하는 기능 (bool, 첫 등장 iterator)
    {
        bool found = false;
        vector<int>::iterator it;

        // TODO
        for (unsigned int i = 0; i < v.size(); i++)
        {
            int data = v[i];

            if (data % 11 == 0)
            {
                found = true;
                it = v.begin() + i;
                break;
            }
        }

        struct  CanDivideBy11
        {
            bool operator()(int n)
            {
                return (n % 11) == 0;
            }
        };
        
        vector<int>::iterator itFind = find_if(v.begin(), v.end(), CanDivideBy11());
        //vector<int>::iterator itFind = find_if(v.begin(), v.end(), [](int n) {return (n % 11) == 0; }); // 추후에 나올 람다식 버전 / 일회성 함수
    
        if (itFind == v.end())
        {
            cout << "실패" << endl;
        }
        else
        {
            cout << "성공" << endl;
        }
    }

    // Q3) 홀수인 숫자의 개수는? (count)
    {
        int count = 0;

        // TODO
        for (unsigned int i = 0; i < v.size(); i++)
        {
            int data = v[i];

            if (data % 2 != 0)
            {
                count++;
            }
        }

        struct IsOdd
        {
            bool operator()(int n)
            {
                return (n % 2) != 0;
            }
        };

        int n = count_if(v.begin(), v.end(), IsOdd());

        // 모든 데이터가 조건을 만족하는가
        bool b1 = all_of(v.begin(), v.end(), IsOdd()); // 모든 데이터가 홀수인가
        bool b2 = any_of(v.begin(), v.end(), IsOdd()); // 홀수인 데이터가 하나라도 있는가
        bool b3 = none_of(v.begin(), v.end(), IsOdd()); // 모든 데이터가 홀수가 아닌가
    }

    // Q4) 벡터에 들어가 있는 모든 숫자들에 3 곱하기
    {
        int b = 3; // break 용

        for (unsigned int i = 0; i < v.size(); i++)
        {
            v[i] *= 3;
        }

        struct MultiplyBy3
        {
            void operator()(int& n)
            {
                n = n * 3;
            }
        };

        for_each(v.begin(), v.end(), MultiplyBy3()); // list나 vector 같은 다른 컨테이너들과의 호환성이 좋다
    }

    // 홀수인 데이터를 일괄 삭제
    {
        //for (vector<int>::iterator it = v.begin(); it != v.end();)
        //{
        //    if ((*it % 2) != 0)
        //        it = v.erase(it); // vector의 경우 중간 삽입 삭제의 효율이 좋지 않다.
        //    else // 또한, iterator로 루프 할 때 vector 자체를 건드리는 행위는 매우 위험
        //        ++it;
        //}

        v.clear();

        v.push_back(1);
        v.push_back(4);
        v.push_back(3);
        v.push_back(5);
        v.push_back(8);
        v.push_back(2);

        /* // remove_if 동작 방식
        template<class ForwardIt, class UnaryPredicate>
        ForwardIt remove_if(ForwardIt first, ForwardIt last, UnaryPredicate p)
        {
            first = std::find_if(first, last, p);
            if (first != last)
                for (ForwardIt i = first; ++i != last;)
                    if (!p(*i))
                        *first++ = std::move(*i);
            return first;
        }
        */

        // 1 4 3 5 8 2 -> 4 8 2 5 8 2 // 삭제가 아닌 필요값을 찾아서 앞당기는 방식

        //remove(v.begin(), v.end(), 4); // remove와 remove_if는 결국 비슷한 형식으로 동작
        
        struct IsOdd
        {
            bool operator()(int n)
            {
                return (n % 2) != 0;
            }
        };
        
        //vector<int>::iterator it = remove_if(v.begin(), v.end(), IsOdd()); // 해당 버전이 remove에 비해 조금 더 일반적
        //v.erase(it, v.end()); // remove에는 항상 erase가 붙어다닌다. 필요값을 앞당기며 남은 필요없는 값을 제거하기 위함

        v.erase(remove_if(v.begin(), v.end(), IsOdd()), v.end()); // 축약버전

    }

    return 0;
}

[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part1: C++ 프로그래밍 입문 - 인프런 | 강의
 
C++ 카테고리의 글은 인프런 Rookiss님의 강의를 공부하며 정리하는 내용입니다.
이미 알고 있는 내용도 다시 정리 되어있을 수 있습니다.

 

모든 글은 제가 공부하기 위해 작성합니다.

 

'Develop > C++' 카테고리의 다른 글

[C++] 중괄호 초기화 { }  (0) 2023.10.16
[C++] auto  (0) 2023.10.03
[C++] 연습 문제  (0) 2023.08.31
[C++] set, multimap, multiset  (0) 2023.08.23
[C++] map #2  (0) 2023.07.13