C++ Algorithm Count | "카운트 알고리즘" 가이드

C++ Algorithm Count | "카운트 알고리즘" 가이드

이 글의 핵심

C++ Algorithm Count에 대한 실전 가이드입니다.

들어가며

카운트 알고리즘은 컨테이너의 요소를 세거나 조건을 검사하는 알고리즘입니다. count, count_if, all_of, any_of, none_of 등을 제공합니다.


1. count

기본 사용

#include <algorithm>
#include <vector>
#include <iostream>

int main() {
    std::vector<int> v = {1, 2, 3, 2, 4, 2, 5};
    
    // 2의 개수
    int count = std::count(v.begin(), v.end(), 2);
    
    std::cout << "2의 개수: " << count << std::endl;  // 3
    
    return 0;
}

문자열에서 사용

#include <algorithm>
#include <string>
#include <iostream>

int main() {
    std::string text = "hello world";
    
    // 'l'의 개수
    int count = std::count(text.begin(), text.end(), 'l');
    
    std::cout << "'l'의 개수: " << count << std::endl;  // 3
    
    return 0;
}

2. count_if

조건부 카운트

#include <algorithm>
#include <vector>
#include <iostream>

int main() {
    std::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    
    // 짝수 개수
    int evenCount = std::count_if(v.begin(), v.end(),  {
        return x % 2 == 0;
    });
    
    std::cout << "짝수 개수: " << evenCount << std::endl;  // 5
    
    // 5보다 큰 수
    int greaterThan5 = std::count_if(v.begin(), v.end(),  {
        return x > 5;
    });
    
    std::cout << "5보다 큰 수: " << greaterThan5 << std::endl;  // 5
    
    return 0;
}

구조체에서 사용

#include <algorithm>
#include <vector>
#include <string>
#include <iostream>

struct Student {
    std::string name;
    int score;
};

int main() {
    std::vector<Student> students = {
        {"Alice", 85},
        {"Bob", 92},
        {"Charlie", 78},
        {"David", 95},
        {"Eve", 88}
    };
    
    // 90점 이상
    int highScores = std::count_if(students.begin(), students.end(),
         {
            return s.score >= 90;
        });
    
    std::cout << "90점 이상: " << highScores << "명" << std::endl;  // 2명
    
    return 0;
}

3. all_of, any_of, none_of

all_of (모두)

#include <algorithm>
#include <vector>
#include <iostream>

int main() {
    std::vector<int> v1 = {2, 4, 6, 8, 10};
    std::vector<int> v2 = {2, 4, 5, 8, 10};
    
    // 모두 짝수?
    bool allEven1 = std::all_of(v1.begin(), v1.end(),  {
        return x % 2 == 0;
    });
    
    bool allEven2 = std::all_of(v2.begin(), v2.end(),  {
        return x % 2 == 0;
    });
    
    std::cout << "v1 모두 짝수: " << std::boolalpha << allEven1 << std::endl;  // true
    std::cout << "v2 모두 짝수: " << std::boolalpha << allEven2 << std::endl;  // false
    
    return 0;
}

any_of (하나라도)

#include <algorithm>
#include <vector>
#include <iostream>

int main() {
    std::vector<int> v1 = {1, 3, 5, 7, 9};
    std::vector<int> v2 = {1, 3, 4, 7, 9};
    
    // 하나라도 짝수?
    bool hasEven1 = std::any_of(v1.begin(), v1.end(),  {
        return x % 2 == 0;
    });
    
    bool hasEven2 = std::any_of(v2.begin(), v2.end(),  {
        return x % 2 == 0;
    });
    
    std::cout << "v1 짝수 있음: " << std::boolalpha << hasEven1 << std::endl;  // false
    std::cout << "v2 짝수 있음: " << std::boolalpha << hasEven2 << std::endl;  // true
    
    return 0;
}

none_of (없음)

#include <algorithm>
#include <vector>
#include <iostream>

int main() {
    std::vector<int> v = {1, 3, 5, 7, 9};
    
    // 음수 없음?
    bool noNegative = std::none_of(v.begin(), v.end(),  {
        return x < 0;
    });
    
    std::cout << "음수 없음: " << std::boolalpha << noNegative << std::endl;  // true
    
    return 0;
}

4. 자주 발생하는 문제

문제 1: 빈 범위

#include <algorithm>
#include <vector>
#include <iostream>

int main() {
    std::vector<int> empty;
    
    // count: 0
    int count = std::count(empty.begin(), empty.end(), 5);
    std::cout << "count: " << count << std::endl;  // 0
    
    // all_of: true (공허한 참)
    bool all = std::all_of(empty.begin(), empty.end(),  { return x > 0; });
    std::cout << "all_of: " << std::boolalpha << all << std::endl;  // true
    
    // any_of: false
    bool any = std::any_of(empty.begin(), empty.end(),  { return x > 0; });
    std::cout << "any_of: " << std::boolalpha << any << std::endl;  // false
    
    // none_of: true
    bool none = std::none_of(empty.begin(), empty.end(),  { return x < 0; });
    std::cout << "none_of: " << std::boolalpha << none << std::endl;  // true
    
    return 0;
}

문제 2: 반환 타입

#include <algorithm>
#include <vector>
#include <iostream>

int main() {
    std::vector<int> v = {1, 2, 3, 4, 5};
    
    // count 반환 타입: difference_type (보통 ptrdiff_t)
    auto count = std::count(v.begin(), v.end(), 3);
    
    // ✅ 명시적 타입
    size_t count2 = std::count(v.begin(), v.end(), 3);
    
    std::cout << "count: " << count << std::endl;
    std::cout << "count2: " << count2 << std::endl;
    
    return 0;
}

문제 3: 단락 평가

#include <algorithm>
#include <vector>
#include <iostream>

int main() {
    std::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    
    int checks = 0;
    
    // any_of: 첫 true에서 중단
    bool hasEven = std::any_of(v.begin(), v.end(), [&checks](int x) {
        ++checks;
        std::cout << "검사: " << x << std::endl;
        return x % 2 == 0;
    });
    
    std::cout << "짝수 있음: " << std::boolalpha << hasEven << std::endl;
    std::cout << "검사 횟수: " << checks << std::endl;  // 2 (1, 2만 검사)
    
    return 0;
}

출력:

검사: 1
검사: 2
짝수 있음: true
검사 횟수: 2

문제 4: 성능

#include <algorithm>
#include <vector>
#include <iostream>

int main() {
    std::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    
    // ❌ 여러 번 순회
    int even = std::count_if(v.begin(), v.end(),  { return x % 2 == 0; });
    int odd = std::count_if(v.begin(), v.end(),  { return x % 2 != 0; });
    int gt5 = std::count_if(v.begin(), v.end(),  { return x > 5; });
    
    // ✅ 한 번에 순회
    int evenCount = 0, oddCount = 0, gt5Count = 0;
    for (int x : v) {
        if (x % 2 == 0) ++evenCount;
        else ++oddCount;
        if (x > 5) ++gt5Count;
    }
    
    std::cout << "짝수: " << evenCount << ", 홀수: " << oddCount 
              << ", >5: " << gt5Count << std::endl;
    
    return 0;
}

5. 실전 예제: 통계 유틸리티

#include <algorithm>
#include <vector>
#include <numeric>
#include <cmath>
#include <iostream>

class Statistics {
public:
    // 기본 통계
    static void analyze(const std::vector<int>& data) {
        if (data.empty()) {
            std::cout << "데이터 없음" << std::endl;
            return;
        }
        
        // 개수
        size_t count = data.size();
        
        // 합계
        int sum = std::accumulate(data.begin(), data.end(), 0);
        
        // 평균
        double mean = static_cast<double>(sum) / count;
        
        // 최소/최대
        auto [minIt, maxIt] = std::minmax_element(data.begin(), data.end());
        
        // 짝수/홀수
        int evenCount = std::count_if(data.begin(), data.end(),  {
            return x % 2 == 0;
        });
        int oddCount = count - evenCount;
        
        // 양수/음수/0
        int positive = std::count_if(data.begin(), data.end(),  { return x > 0; });
        int negative = std::count_if(data.begin(), data.end(),  { return x < 0; });
        int zero = std::count(data.begin(), data.end(), 0);
        
        // 출력
        std::cout << "=== 통계 ===" << std::endl;
        std::cout << "개수: " << count << std::endl;
        std::cout << "합계: " << sum << std::endl;
        std::cout << "평균: " << mean << std::endl;
        std::cout << "최소: " << *minIt << std::endl;
        std::cout << "최대: " << *maxIt << std::endl;
        std::cout << "짝수: " << evenCount << ", 홀수: " << oddCount << std::endl;
        std::cout << "양수: " << positive << ", 음수: " << negative << ", 0: " << zero << std::endl;
    }
    
    // 조건 검사
    static void validate(const std::vector<int>& data) {
        // 모두 양수?
        bool allPositive = std::all_of(data.begin(), data.end(),  {
            return x > 0;
        });
        
        // 하나라도 음수?
        bool hasNegative = std::any_of(data.begin(), data.end(),  {
            return x < 0;
        });
        
        // 0 없음?
        bool noZero = std::none_of(data.begin(), data.end(),  {
            return x == 0;
        });
        
        std::cout << "\n=== 검증 ===" << std::endl;
        std::cout << "모두 양수: " << std::boolalpha << allPositive << std::endl;
        std::cout << "음수 있음: " << std::boolalpha << hasNegative << std::endl;
        std::cout << "0 없음: " << std::boolalpha << noZero << std::endl;
    }
    
    // 범위 검사
    static bool inRange(const std::vector<int>& data, int min, int max) {
        return std::all_of(data.begin(), data.end(), [min, max](int x) {
            return x >= min && x <= max;
        });
    }
};

int main() {
    std::vector<int> data = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    
    Statistics::analyze(data);
    Statistics::validate(data);
    
    std::cout << "\n범위 [1, 10]: " << std::boolalpha 
              << Statistics::inRange(data, 1, 10) << std::endl;  // true
    
    std::cout << "범위 [1, 5]: " << std::boolalpha 
              << Statistics::inRange(data, 1, 5) << std::endl;  // false
    
    return 0;
}

출력:

=== 통계 ===
개수: 10
합계: 55
평균: 5.5
최소: 1
최대: 10
짝수: 5, 홀수: 5
양수: 10, 음수: 0, 0: 0

=== 검증 ===
모두 양수: true
음수 있음: false
0 없음: true

범위 [1, 10]: true
범위 [1, 5]: false

6. 카운트 알고리즘 비교

함수 시그니처

#include <algorithm>

// count: 값 개수
template<class InputIt, class T>
typename iterator_traits<InputIt>::difference_type
count(InputIt first, InputIt last, const T& value);

// count_if: 조건 개수
template<class InputIt, class UnaryPredicate>
typename iterator_traits<InputIt>::difference_type
count_if(InputIt first, InputIt last, UnaryPredicate p);

// all_of: 모두 만족?
template<class InputIt, class UnaryPredicate>
bool all_of(InputIt first, InputIt last, UnaryPredicate p);

// any_of: 하나라도 만족?
template<class InputIt, class UnaryPredicate>
bool any_of(InputIt first, InputIt last, UnaryPredicate p);

// none_of: 모두 불만족?
template<class InputIt, class UnaryPredicate>
bool none_of(InputIt first, InputIt last, UnaryPredicate p);

비교 표

알고리즘반환 타입시간복잡도단락 평가빈 범위
countdifference_typeO(n)0
count_ifdifference_typeO(n)0
all_ofboolO(n)true
any_ofboolO(n)false
none_ofboolO(n)true

정리

핵심 요약

  1. count: 특정 값 개수
  2. count_if: 조건 만족 개수
  3. all_of: 모두 만족? (단락 평가)
  4. any_of: 하나라도 만족? (단락 평가)
  5. none_of: 모두 불만족? (단락 평가)
  6. 시간복잡도: 모두 O(n)

카운트 알고리즘 선택 가이드

목적알고리즘예시
특정 값 개수countcount(v.begin(), v.end(), 5)
조건 만족 개수count_ifcount_if(v.begin(), v.end(), isEven)
모두 만족?all_ofall_of(v.begin(), v.end(), isPositive)
하나라도 만족?any_ofany_of(v.begin(), v.end(), isNegative)
모두 불만족?none_ofnone_of(v.begin(), v.end(), isZero)

실전 팁

사용 원칙:

  • 특정 값 개수는 count
  • 조건부 개수는 count_if
  • 검증은 all_of, any_of, none_of
  • 단락 평가 활용 (성능)

성능:

  • 모두 O(n) 순회
  • any_of, all_of는 단락 평가 (조기 종료)
  • 여러 조건은 한 번에 순회
  • 빈 범위 체크

주의사항:

  • 빈 범위: all_of는 true, any_of는 false
  • 반환 타입: countdifference_type
  • 단락 평가: any_of는 첫 true에서 중단
  • 부작용 금지: predicate는 순수 함수

다음 단계

  • C++ Algorithm Find
  • C++ Algorithm Remove
  • C++ Algorithm Sort

관련 글

  • C++ STL 알고리즘 기초 완벽 가이드 | sort·find