Skip to Content
💻 코리아IT아카데미 신촌 - 프로그래밍 학습 자료
C++ 프로그래밍Unit 13: 템플릿과 STLTopic 3: STL 알고리즘과 반복자

Topic 3: STL 알고리즘과 반복자 🔄

🎯 학습 목표

  • 반복자(Iterator)의 개념과 활용법 익히기
  • STL 핵심 알고리즘 (sort, find, transform 등) 마스터하기
  • 람다 표현식으로 간결한 코드 작성하기
  • 게임 데이터 분석에 STL 알고리즘 적용하기
  • 함수형 프로그래밍 스타일 경험하기

🧭 반복자가 뭐예요?

반복자는 마치 여행 가이드와 같아요! 컨테이너라는 관광지를 돌아다니면서 각 장소(요소)를 안내해주는 역할을 합니다.

💡 비유: 박물관에서 전시품을 하나씩 안내해주는 도슨트처럼, 반복자는 컨테이너의 요소들을 하나씩 가리켜주는 포인터예요!

🎯 반복자 기초

#include <iostream> #include <vector> #include <list> using namespace std; int main() { vector<int> scores = {100, 85, 92, 78, 95}; cout << "🎮 점수 목록 (반복자 사용):\n"; // begin()과 end() 사용 for (auto it = scores.begin(); it != scores.end(); ++it) { cout << "📊 점수: " << *it << "\n"; // *it로 값 접근 } cout << "\n🔄 역순으로 출력:\n"; // 역방향 반복자 사용 for (auto it = scores.rbegin(); it != scores.rend(); ++it) { cout << "📊 점수: " << *it << "\n"; } // list에서도 동일하게 작동 list<string> players = {"Alice", "Bob", "Charlie"}; cout << "\n👥 플레이어 목록:\n"; for (auto it = players.begin(); it != players.end(); ++it) { cout << "👤 " << *it << "\n"; } return 0; }

🔍 STL 알고리즘 마스터하기

1️⃣ 정렬 알고리즘 (sort)

#include <iostream> #include <vector> #include <algorithm> #include <string> using namespace std; struct Player { string name; int score; int level; }; int main() { vector<Player> players = { {"Alice", 1500, 25}, {"Bob", 2100, 30}, {"Charlie", 800, 15}, {"Diana", 1800, 28} }; cout << "🎮 원래 플레이어 목록:\n"; for (const auto& p : players) { cout << "👤 " << p.name << " - " << p.score << "점 (Lv." << p.level << ")\n"; } // 점수 기준 정렬 (내림차순) sort(players.begin(), players.end(), [](const Player& a, const Player& b) { return a.score > b.score; // 람다 표현식! }); cout << "\n🏆 점수순 정렬:\n"; for (const auto& p : players) { cout << "👤 " << p.name << " - " << p.score << "점 (Lv." << p.level << ")\n"; } // 레벨 기준 정렬 sort(players.begin(), players.end(), [](const Player& a, const Player& b) { return a.level < b.level; }); cout << "\n⭐ 레벨순 정렬:\n"; for (const auto& p : players) { cout << "👤 " << p.name << " - " << p.score << "점 (Lv." << p.level << ")\n"; } return 0; }

2️⃣ 검색 알고리즘 (find, find_if)

#include <iostream> #include <vector> #include <algorithm> #include <string> using namespace std; int main() { vector<string> items = { "Magic Sword", "Health Potion", "Shield", "Mana Crystal", "Fire Scroll", "Ice Shield" }; cout << "🎒 보유 아이템:\n"; for (const auto& item : items) { cout << " ✨ " << item << "\n"; } // 특정 아이템 찾기 string searchItem = "Shield"; auto found = find(items.begin(), items.end(), searchItem); if (found != items.end()) { cout << "\n✅ '" << searchItem << "' 발견! 위치: " << (found - items.begin()) << "\n"; } // 조건에 맞는 아이템 찾기 (Shield가 들어간 아이템) auto shieldItem = find_if(items.begin(), items.end(), [](const string& item) { return item.find("Shield") != string::npos; }); if (shieldItem != items.end()) { cout << "🛡️ 방어구 발견: " << *shieldItem << "\n"; } // 모든 Shield 아이템 찾기 cout << "\n🛡️ 모든 방어구:\n"; for (auto it = items.begin(); it != items.end(); ++it) { if (it->find("Shield") != string::npos) { cout << " ⚔️ " << *it << "\n"; } } return 0; }

3️⃣ 변환 알고리즘 (transform)

#include <iostream> #include <vector> #include <algorithm> #include <string> using namespace std; int main() { vector<int> originalScores = {100, 85, 92, 78, 95, 88}; vector<int> boostedScores(originalScores.size()); cout << "🎮 원래 점수:\n"; for (int score : originalScores) { cout << "📊 " << score << " "; } cout << "\n\n"; // 모든 점수에 보너스 20% 추가 transform(originalScores.begin(), originalScores.end(), boostedScores.begin(), [](int score) { return static_cast<int>(score * 1.2); }); cout << "🚀 보너스 적용 후:\n"; for (int score : boostedScores) { cout << "📊 " << score << " "; } cout << "\n\n"; // 플레이어 이름을 대문자로 변환 vector<string> players = {"alice", "bob", "charlie", "diana"}; vector<string> upperPlayers(players.size()); transform(players.begin(), players.end(), upperPlayers.begin(), [](string name) { for (char& c : name) { c = toupper(c); } return name; }); cout << "👥 플레이어 이름 (대문자):\n"; for (const auto& name : upperPlayers) { cout << "👤 " << name << "\n"; } return 0; }

🚀 람다 표현식 마스터하기

#include <iostream> #include <vector> #include <algorithm> using namespace std; int main() { vector<int> numbers = {5, 2, 8, 1, 9, 3}; cout << "🔢 원래 숫자: "; for (int n : numbers) cout << n << " "; cout << "\n\n"; // 1. 기본 람다 - 짝수만 출력 cout << "🎯 짝수만 출력:\n"; for_each(numbers.begin(), numbers.end(), [](int n) { if (n % 2 == 0) { cout << "✨ " << n << "\n"; } }); // 2. 캡처를 이용한 람다 int bonus = 10; cout << "\n🚀 보너스 +" << bonus << " 적용:\n"; for_each(numbers.begin(), numbers.end(), [bonus](int n) { // bonus 변수 캡처 cout << "📊 " << (n + bonus) << "\n"; }); // 3. 참조 캡처로 값 수정 int multiplier = 2; cout << "\n🔄 배수 적용 (x" << multiplier << "):\n"; for_each(numbers.begin(), numbers.end(), [&multiplier](int& n) { // 참조로 캡처 n *= multiplier; cout << "🔢 " << n << "\n"; }); // 4. 모든 변수 캡처 string prefix = "점수: "; for_each(numbers.begin(), numbers.end(), [=](int n) { // 모든 지역변수를 값으로 캡처 cout << "📈 " << prefix << n << "\n"; }); return 0; }

🎮 실전 프로젝트: 게임 데이터 분석 시스템

#include <iostream> #include <vector> #include <algorithm> #include <numeric> #include <string> #include <map> using namespace std; struct GameSession { string playerName; int score; int playtime; // 분 단위 int level; bool victory; }; class GameAnalyzer { private: vector<GameSession> sessions; public: void addSession(const GameSession& session) { sessions.push_back(session); } // 전체 통계 분석 void analyzeOverallStats() { cout << "📊 전체 게임 분석 결과\n"; cout << "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"; // 총 세션 수 cout << "🎮 총 게임 세션: " << sessions.size() << "회\n"; // 평균 점수 double avgScore = accumulate(sessions.begin(), sessions.end(), 0.0, [](double sum, const GameSession& s) { return sum + s.score; }) / sessions.size(); cout << "📈 평균 점수: " << avgScore << "점\n"; // 평균 플레이 시간 double avgTime = accumulate(sessions.begin(), sessions.end(), 0.0, [](double sum, const GameSession& s) { return sum + s.playtime; }) / sessions.size(); cout << "⏰ 평균 플레이 시간: " << avgTime << "분\n"; // 승률 계산 int victories = count_if(sessions.begin(), sessions.end(), [](const GameSession& s) { return s.victory; }); double winRate = (double)victories / sessions.size() * 100; cout << "🏆 전체 승률: " << winRate << "%\n"; } // 탑 플레이어 분석 void findTopPlayers(int topN = 3) { cout << "\n🥇 TOP " << topN << " 플레이어:\n"; cout << "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"; // 플레이어별 최고 점수 계산 map<string, int> playerBestScores; for (const auto& session : sessions) { playerBestScores[session.playerName] = max(playerBestScores[session.playerName], session.score); } // vector로 변환 후 정렬 vector<pair<int, string>> rankings; for (const auto& pair : playerBestScores) { rankings.push_back({pair.second, pair.first}); } sort(rankings.begin(), rankings.end(), greater<pair<int, string>>()); for (int i = 0; i < min(topN, (int)rankings.size()); i++) { string medal = (i == 0) ? "🥇" : (i == 1) ? "🥈" : "🥉"; cout << medal << " " << rankings[i].second << ": " << rankings[i].first << "점\n"; } } // 레벨별 분석 void analyzeLevelProgression() { cout << "\n⭐ 레벨별 분석:\n"; cout << "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"; // 레벨별 그룹화 map<int, vector<GameSession*>> levelGroups; for (auto& session : sessions) { levelGroups[session.level].push_back(&session); } for (const auto& pair : levelGroups) { int level = pair.first; const auto& levelSessions = pair.second; // 해당 레벨 평균 점수 double avgScore = accumulate(levelSessions.begin(), levelSessions.end(), 0.0, [](double sum, const GameSession* s) { return sum + s->score; }) / levelSessions.size(); // 해당 레벨 승률 int wins = count_if(levelSessions.begin(), levelSessions.end(), [](const GameSession* s) { return s->victory; }); double winRate = (double)wins / levelSessions.size() * 100; cout << "🎯 레벨 " << level << ": "; cout << "평균 " << avgScore << "점, "; cout << "승률 " << winRate << "%\n"; } } // 성과 향상 분석 void analyzeImprovement() { cout << "\n📈 플레이어 성과 향상 분석:\n"; cout << "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"; // 플레이어별 세션들을 시간순으로 그룹화 map<string, vector<GameSession*>> playerSessions; for (auto& session : sessions) { playerSessions[session.playerName].push_back(&session); } for (const auto& pair : playerSessions) { const string& player = pair.first; const auto& playerGames = pair.second; if (playerGames.size() < 2) continue; // 게임이 2회 이상인 경우만 // 처음과 마지막 게임 비교 int firstScore = playerGames.front()->score; int lastScore = playerGames.back()->score; int improvement = lastScore - firstScore; cout << "👤 " << player << ": "; if (improvement > 0) { cout << "📈 +" << improvement << "점 향상! "; cout << "(" << firstScore << " → " << lastScore << ")\n"; } else if (improvement < 0) { cout << "📉 " << improvement << "점 하락 "; cout << "(" << firstScore << " → " << lastScore << ")\n"; } else { cout << "📊 동일한 점수 유지\n"; } } } }; int main() { cout << "🎮 게임 데이터 분석 시스템\n\n"; GameAnalyzer analyzer; // 샘플 데이터 추가 analyzer.addSession({"Alice", 1200, 45, 10, true}); analyzer.addSession({"Bob", 850, 30, 8, false}); analyzer.addSession({"Alice", 1500, 50, 12, true}); analyzer.addSession({"Charlie", 950, 35, 9, true}); analyzer.addSession({"Bob", 1100, 40, 10, true}); analyzer.addSession({"Diana", 1800, 60, 15, true}); analyzer.addSession({"Alice", 1650, 55, 14, true}); analyzer.addSession({"Charlie", 1200, 45, 11, false}); // 분석 실행 analyzer.analyzeOverallStats(); analyzer.findTopPlayers(); analyzer.analyzeLevelProgression(); analyzer.analyzeImprovement(); return 0; }

🧠 유용한 STL 알고리즘 모음

#include <iostream> #include <vector> #include <algorithm> #include <numeric> using namespace std; int main() { vector<int> numbers = {5, 2, 8, 1, 9, 3, 7, 6, 4}; cout << "🔢 원본 데이터: "; for (int n : numbers) cout << n << " "; cout << "\n\n"; // 1. 정렬 관련 sort(numbers.begin(), numbers.end()); cout << "📈 오름차순 정렬: "; for (int n : numbers) cout << n << " "; cout << "\n"; // 2. 최대/최소 찾기 auto maxIt = max_element(numbers.begin(), numbers.end()); auto minIt = min_element(numbers.begin(), numbers.end()); cout << "🔝 최댓값: " << *maxIt << ", 최솟값: " << *minIt << "\n"; // 3. 합계 구하기 int sum = accumulate(numbers.begin(), numbers.end(), 0); cout << "➕ 총합: " << sum << "\n"; // 4. 조건 확인 bool allPositive = all_of(numbers.begin(), numbers.end(), [](int n) { return n > 0; }); cout << "✅ 모두 양수인가? " << (allPositive ? "Yes" : "No") << "\n"; // 5. 개수 세기 int evenCount = count_if(numbers.begin(), numbers.end(), [](int n) { return n % 2 == 0; }); cout << "🔢 짝수 개수: " << evenCount << "개\n"; // 6. 중복 제거 vector<int> duplicates = {1, 2, 2, 3, 3, 3, 4, 5, 5}; sort(duplicates.begin(), duplicates.end()); auto last = unique(duplicates.begin(), duplicates.end()); duplicates.erase(last, duplicates.end()); cout << "🎯 중복 제거 결과: "; for (int n : duplicates) cout << n << " "; cout << "\n"; return 0; }

💡 핵심 정리

  • 반복자: 컨테이너 요소를 가리키는 포인터 역할 🧭
  • sort: 데이터 정렬의 만능 도구 📊
  • find/find_if: 원하는 데이터 찾기 🔍
  • transform: 모든 요소에 함수 적용 🔄
  • 람다 표현식: 간결한 함수 정의 방법 ⚡
  • accumulate: 누적 연산(합, 곱 등) ➕
  • STL 알고리즘 = 성능 + 편의성! 🚀

✅ 실습 체크리스트

🚀 다음 시간 예고

다음 시간에는 **스마트 포인터와 현대적 C++**을 배워볼 예정이에요! 🎯

  • 메모리 누수 문제와 해결책
  • unique_ptr, shared_ptr, weak_ptr 활용
  • RAII 패턴으로 안전한 메모리 관리
  • 자동 메모리 관리 시스템 구현

더 이상 메모리 걱정 없이 안전한 C++ 코드를 작성하는 방법을 알아보죠! 🛡️

Last updated on