Skip to Content
💻 코리아IT아카데미 신촌 - 프로그래밍 학습 자료
C++ 프로그래밍Unit 13: 템플릿과 STLTopic 2: STL 컨테이너 마스터하기

Topic 2: STL 컨테이너 마스터하기 📦

🎯 학습 목표

  • STL 컨테이너의 종류와 특징 이해하기
  • vector, list, deque의 성능 차이 파악하기
  • map, set 등 연관 컨테이너 활용하기
  • 상황에 맞는 컨테이너 선택하기
  • 실전 게임 리더보드 시스템 구현하기

🧰 STL 컨테이너가 뭐예요?

레고를 만들 때 다양한 형태의 블록들이 필요하듯이, 프로그래밍에서도 다양한 형태의 데이터 저장소가 필요해요! STL 컨테이너는 마치 만능 도구상자처럼 상황에 맞는 저장 방식을 제공합니다.

💡 비유: 요리할 때 접시, 그릇, 컵, 팬이 각각 다른 용도가 있듯이, 컨테이너도 각자 특별한 능력이 있어요!

📋 순차 컨테이너 (Sequential Containers)

1️⃣ vector - 동적 배열의 왕 👑

#include <iostream> #include <vector> using namespace std; int main() { // 플레이어 점수 관리 vector<int> scores; // 점수 추가 (뒤에서부터) scores.push_back(1200); scores.push_back(850); scores.push_back(2100); scores.push_back(750); cout << "🎮 현재 점수 목록: "; for (int score : scores) { cout << score << " "; } cout << "\n\n"; // 인덱스로 접근 (빠름! O(1)) cout << "🥇 최고 점수 확인: " << scores[2] << "점\n"; // 크기 정보 cout << "📊 총 플레이어 수: " << scores.size() << "명\n"; cout << "💾 현재 용량: " << scores.capacity() << "\n\n"; // 마지막 요소 제거 scores.pop_back(); cout << "❌ 마지막 플레이어 제거 후 크기: " << scores.size() << "\n"; return 0; }

🚀 vector의 장점:

  • 인덱스 접근이 빠름 (O(1))
  • 메모리 효율적
  • 뒤에 요소 추가/제거가 빠름

⚠️ vector의 단점:

  • 중간 삽입/삭제가 느림 (O(n))
  • 용량 초과시 전체 복사 발생

2️⃣ list - 연결 리스트의 달인 🔗

#include <iostream> #include <list> #include <string> using namespace std; int main() { // 대기열 관리 (앞뒤 삽입이 자유로움) list<string> waitingQueue; // 일반 플레이어들 추가 waitingQueue.push_back("Player1"); waitingQueue.push_back("Player2"); waitingQueue.push_back("Player3"); // VIP 플레이어는 맨 앞으로! waitingQueue.push_front("VIP_Player"); cout << "🎯 현재 대기열:\n"; for (const auto& player : waitingQueue) { cout << " 👤 " << player << "\n"; } // 중간에 특별 플레이어 삽입 auto it = waitingQueue.begin(); advance(it, 2); // 2번째 위치로 이동 waitingQueue.insert(it, "Special_Player"); cout << "\n🌟 특별 플레이어 추가 후:\n"; for (const auto& player : waitingQueue) { cout << " 👤 " << player << "\n"; } return 0; }

🚀 list의 장점:

  • 중간 삽입/삭제가 빠름 (O(1))
  • 앞뒤 모든 위치에서 효율적

⚠️ list의 단점:

  • 인덱스 접근 불가 (순차 접근만)
  • 메모리 오버헤드 있음

3️⃣ deque - 양쪽 끝의 마법사 🎭

#include <iostream> #include <deque> using namespace std; int main() { // 최근 게임 히스토리 (앞뒤로 추가/제거) deque<string> gameHistory; // 게임 기록 추가 gameHistory.push_back("Level 1 Complete"); gameHistory.push_back("Level 2 Complete"); gameHistory.push_back("Level 3 Failed"); // 긴급 공지는 맨 앞으로 gameHistory.push_front("🚨 Emergency Update!"); cout << "📜 게임 히스토리:\n"; for (int i = 0; i < gameHistory.size(); i++) { cout << "[" << i << "] " << gameHistory[i] << "\n"; } // 오래된 기록 제거 gameHistory.pop_back(); gameHistory.pop_front(); cout << "\n🧹 정리 후:\n"; for (const auto& record : gameHistory) { cout << " 📝 " << record << "\n"; } return 0; }

🗺️ 연관 컨테이너 (Associative Containers)

1️⃣ map - 키-값 쌍의 마스터 🗝️

#include <iostream> #include <map> #include <string> using namespace std; int main() { // 플레이어별 최고 점수 관리 map<string, int> playerScores; // 점수 등록 playerScores["Alice"] = 1500; playerScores["Bob"] = 2100; playerScores["Charlie"] = 800; playerScores["Diana"] = 1800; cout << "🏆 플레이어별 최고 점수:\n"; for (const auto& pair : playerScores) { cout << "👤 " << pair.first << ": " << pair.second << "점\n"; } // 특정 플레이어 점수 조회 string searchPlayer = "Bob"; if (playerScores.find(searchPlayer) != playerScores.end()) { cout << "\n🔍 " << searchPlayer << "의 점수: " << playerScores[searchPlayer] << "점\n"; } // 점수 업데이트 playerScores["Alice"] = 1650; // 새 최고 점수! cout << "🆙 Alice 점수 업데이트: " << playerScores["Alice"] << "점\n"; return 0; }

2️⃣ set - 중복 없는 컬렉션 🎯

#include <iostream> #include <set> #include <string> using namespace std; int main() { // 유니크한 아이템 컬렉션 set<string> uniqueItems; // 아이템 추가 (중복 자동 제거) uniqueItems.insert("Magic Sword"); uniqueItems.insert("Shield of Light"); uniqueItems.insert("Magic Sword"); // 중복! 무시됨 uniqueItems.insert("Health Potion"); uniqueItems.insert("Magic Sword"); // 또 중복! 무시됨 cout << "🎒 보유 아이템 (중복 제거됨):\n"; for (const auto& item : uniqueItems) { cout << " ✨ " << item << "\n"; } // 아이템 보유 확인 string checkItem = "Magic Sword"; if (uniqueItems.count(checkItem)) { cout << "\n✅ " << checkItem << " 보유중!\n"; } cout << "📊 총 아이템 수: " << uniqueItems.size() << "개\n"; return 0; }

🎮 실전 프로젝트: 게임 리더보드 시스템

#include <iostream> #include <vector> #include <map> #include <set> #include <algorithm> #include <string> using namespace std; class GameLeaderboard { private: map<string, int> playerScores; // 플레이어별 최고 점수 set<string> activePlayers; // 현재 활성 플레이어 vector<pair<int, string>> rankings; // 랭킹 (점수, 이름) public: // 플레이어 점수 등록/업데이트 void updateScore(const string& player, int score) { activePlayers.insert(player); if (playerScores[player] < score) { playerScores[player] = score; cout << "🆙 " << player << " 새 최고 점수: " << score << "점!\n"; } else { cout << "📊 " << player << " 점수: " << score << "점 (최고: " << playerScores[player] << "점)\n"; } updateRankings(); } // 랭킹 업데이트 void updateRankings() { rankings.clear(); for (const auto& pair : playerScores) { rankings.push_back({pair.second, pair.first}); } // 점수 기준 내림차순 정렬 sort(rankings.begin(), rankings.end(), greater<pair<int, string>>()); } // 상위 N명 출력 void showTopPlayers(int topN = 5) { cout << "\n🏆 TOP " << topN << " 랭킹:\n"; cout << "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"; for (int i = 0; i < min(topN, (int)rankings.size()); i++) { string medal = ""; if (i == 0) medal = "🥇"; else if (i == 1) medal = "🥈"; else if (i == 2) medal = "🥉"; else medal = "🏅"; cout << medal << " " << (i + 1) << "위: " << rankings[i].second << " - " << rankings[i].first << "점\n"; } cout << "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"; } // 플레이어 정보 조회 void showPlayerInfo(const string& player) { if (activePlayers.count(player)) { cout << "\n👤 " << player << " 정보:\n"; cout << " 💯 최고 점수: " << playerScores[player] << "점\n"; // 현재 순위 찾기 for (int i = 0; i < rankings.size(); i++) { if (rankings[i].second == player) { cout << " 🏆 현재 순위: " << (i + 1) << "위\n"; break; } } } else { cout << "❌ " << player << " 플레이어를 찾을 수 없습니다.\n"; } } // 전체 통계 void showStats() { cout << "\n📈 게임 통계:\n"; cout << " 👥 총 플레이어 수: " << activePlayers.size() << "명\n"; if (!rankings.empty()) { cout << " 🥇 최고 점수: " << rankings[0].first << "점\n"; cout << " 🥇 최고 점수 보유자: " << rankings[0].second << "\n"; } } }; int main() { cout << "🎮 게임 리더보드 시스템 시작!\n\n"; GameLeaderboard leaderboard; // 플레이어들 점수 등록 leaderboard.updateScore("Alice", 1200); leaderboard.updateScore("Bob", 1500); leaderboard.updateScore("Charlie", 800); leaderboard.updateScore("Diana", 1800); leaderboard.updateScore("Eve", 1350); // Alice 점수 개선 leaderboard.updateScore("Alice", 1650); // 신규 플레이어 leaderboard.updateScore("Frank", 2000); // 랭킹 확인 leaderboard.showTopPlayers(); // 특정 플레이어 정보 leaderboard.showPlayerInfo("Alice"); leaderboard.showPlayerInfo("Bob"); // 전체 통계 leaderboard.showStats(); return 0; }

🎯 컨테이너 선택 가이드

상황추천 컨테이너이유
인덱스로 빠른 접근 필요vectorO(1) 인덱스 접근
중간에 자주 삽입/삭제listO(1) 삽입/삭제
양쪽 끝에서 삽입/삭제deque앞뒤 모두 O(1)
키로 값 찾기mapO(log n) 검색
중복 없는 모음set자동 중복 제거
정렬 필요없는 빠른 검색unordered_map/setO(1) 평균 검색

💡 핵심 정리

  • vector: 동적 배열, 인덱스 접근 강점 📋
  • list: 연결 리스트, 중간 삽입/삭제 강점 🔗
  • deque: 양방향 큐, 앞뒤 삽입/삭제 강점 🎭
  • map: 키-값 쌍, 검색과 정렬 강점 🗝️
  • set: 중복 없는 집합, 유니크 보장 🎯
  • 상황에 맞는 컨테이너 선택이 성능의 핵심!

✅ 실습 체크리스트

🚀 다음 시간 예고

다음 시간에는 STL 알고리즘과 반복자를 배워볼 예정이에요! 🔄

  • 반복자로 컨테이너 순회하기
  • sort, find, transform 등 유용한 알고리즘들
  • 람다 표현식으로 더 간결한 코드 작성
  • 게임 데이터 분석 시스템 구현

컨테이너에 데이터를 넣었다면, 이제 그 데이터를 마음대로 조작하는 방법을 배워보죠! 🎯

Last updated on