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