Menu
Coddy logo textTech

STL 컨테이너

Coddy C++ 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨 — 104개 중 71번째.

STL 컨테이너는 객체 컬렉션을 저장하고 구성하는 템플릿 클래스입니다. 각 컨테이너 유형은 서로 다른 액세스 패턴과 작업에 최적화되어 있습니다. 필요에 맞는 올바른 컨테이너를 선택하는 것은 프로그램의 성능에 큰 영향을 미칠 수 있습니다.

시퀀스 컨테이너(Sequence containers)는 요소들을 특정 순서로 유지합니다:

#include <vector>
#include <list>

std::vector<int> vec = {1, 2, 3};  // 동적 배열, 빠른 임의 접근
vec.push_back(4);                   // 끝에 추가: 분할 상환 O(1)
int x = vec[2];                     // 인덱스로 접근: O(1)

std::list<int> lst = {1, 2, 3};    // 이중 연결 리스트
lst.push_front(0);                  // 앞에 추가: O(1)
lst.push_back(4);                   // 끝에 추가: O(1)

연관 컨테이너(Associative containers)는 빠른 조회를 위해 요소를 정렬된 순서로 저장합니다:

#include <map>
#include <set>

std::set<int> s = {3, 1, 4, 1};    // 고유한 정렬된 요소: {1, 3, 4}
s.insert(2);                        // 삽입: O(log n)
bool found = s.count(3);            // 존재 여부 확인: O(log n)

std::map<std::string, int> ages;   // 키-값 쌍, 키를 기준으로 정렬됨
ages["Alice"] = 25;                 // 삽입/업데이트: O(log n)
ages["Bob"] = 30;
std::cout << ages["Alice"];        // 접근: O(log n)

정렬되지 않은 컨테이너(Unordered containers)는 훨씬 더 빠른 평균 사례 조회를 위해 해시 테이블을 사용합니다:

#include <unordered_map>

std::unordered_map<std::string, int> scores;
scores["player1"] = 100;            // 삽입: 평균 O(1)
scores["player2"] = 200;
std::cout << scores["player1"];    // 접근: 평균 O(1)

빠른 임의 접근이 필요할 때는 vector를, 중간에 빈번한 삽입이 필요할 때는 list를, 정렬된 데이터가 필요할 때는 map/set을, 그리고 조회 속도가 중요하고 순서가 상관없을 때는 unordered_map을 사용하세요.

challenge icon

챌린지

쉬움

서로 다른 STL 컨테이너가 어떻게 다양한 목적에 맞게 사용되는지 보여주는 학생 성적 관리 시스템을 구축해 보겠습니다. 여러 유형의 컨테이너를 사용하여 학생 데이터를 효율적으로 정리하고, 각 작업에 적합한 컨테이너를 선택하는 방법을 배우게 됩니다.

코드를 정리하기 위해 두 개의 파일을 생성합니다:

  • GradeManager.h: 여러 STL 컨테이너를 사용하여 학생 정보를 관리하는 GradeManager 클래스를 정의합니다.

    클래스에서 다음을 사용해야 합니다:

    • 학생 이름을 추가된 순서대로 저장하기 위한 std::vector<std::string>
    • 각 학생의 이름과 성적을 연결하기 위한 std::map<std::string, int>
    • 할당된 모든 고유 성적을 추적하기 위한 std::set<int>

    다음 메서드들을 구현하세요:

    • addStudent(const std::string& name, int grade) — 학생과 성적을 세 개의 컨테이너 모두에 추가합니다.
    • getGrade(const std::string& name) — 맵을 사용하여 주어진 학생 이름에 해당하는 성적을 반환합니다.
    • printRoster() — 벡터를 사용하여 추가된 순서대로 모든 학생 이름을 각 줄에 하나씩 출력합니다.
    • printGrades() — 맵을 사용하여 알파벳 순서대로 모든 학생과 성적을 출력하며(맵이 이를 자동으로 처리함), 각 줄에 name: grade 형식으로 출력합니다.
    • printUniqueGrades() — 셋을 사용하여 모든 고유 성적을 오름차순으로 출력하며(셋이 이를 처리함), 공백으로 구분하고 마지막에 줄바꿈을 추가합니다.
  • main.cpp: 입력을 읽고 각 컨테이너 유형이 어떻게 서로 다른 목적에 기여하는지 보여줍니다.

    여섯 개의 입력을 읽습니다 (각각 별도의 줄에 입력됨):

    1. 첫 번째 학생 이름
    2. 첫 번째 학생 성적 (정수)
    3. 두 번째 학생 이름
    4. 두 번째 학생 성적 (정수)
    5. 세 번째 학생 이름
    6. 세 번째 학생 성적 (정수)

    GradeManager를 생성하고 세 명의 학생을 모두 추가합니다. 그런 다음 서로 다른 컨테이너의 동작을 보여줍니다:

    1. Roster (insertion order):를 출력한 후 printRoster()를 호출합니다.
    2. Grades (alphabetical):를 출력한 후 printGrades()를 호출합니다.
    3. Unique grades:를 출력한 후 printUniqueGrades()를 호출합니다.
    4. 두 번째 학생의 성적을 조회하여 <name>'s grade: <grade> 형식으로 출력합니다.

예를 들어, 입력값이 Charlie, 85, Alice, 90, Bob, 85인 경우:

Roster (insertion order):
Charlie
Alice
Bob
Grades (alphabetical):
Alice: 90
Bob: 85
Charlie: 85
Unique grades:
85 90 
Alice's grade: 90

벡터가 삽입 순서(Charlie, Alice, Bob)를 유지하고, 맵이 키에 따라 자동으로 정렬(Alice, Bob, Charlie)하며, 셋이 고유한 값만 정렬된 순서로 저장(85가 두 번이 아닌 한 번만 나타남)하는 방식에 주목하세요. 각 컨테이너 유형은 서로 다른 작업에 탁월한 성능을 발휘합니다!

치트 시트

STL 컨테이너는 객체 컬렉션을 저장하고 구성하기 위한 템플릿 클래스입니다. 각 유형은 서로 다른 작업에 최적화되어 있습니다.

시퀀스 컨테이너 (Sequence Containers)

요소를 특정 순서로 유지합니다:

#include <vector>
#include <list>

std::vector<int> vec = {1, 2, 3};  // 동적 배열, 빠른 임의 접근
vec.push_back(4);                   // 끝에 추가: 분할 상환 O(1)
int x = vec[2];                     // 인덱스로 접근: O(1)

std::list<int> lst = {1, 2, 3};    // 이중 연결 리스트
lst.push_front(0);                  // 앞에 추가: O(1)
lst.push_back(4);                   // 끝에 추가: O(1)

연관 컨테이너 (Associative Containers)

빠른 조회를 위해 요소를 정렬된 순서로 저장합니다:

#include <map>
#include <set>

std::set<int> s = {3, 1, 4, 1};    // 고유한 정렬된 요소: {1, 3, 4}
s.insert(2);                        // 삽입: O(log n)
bool found = s.count(3);            // 존재 여부 확인: O(log n)

std::map<std::string, int> ages;   // 키-값 쌍, 키를 기준으로 정렬됨
ages["Alice"] = 25;                 // 삽입/업데이트: O(log n)
ages["Bob"] = 30;
std::cout << ages["Alice"];        // 접근: O(log n)

정렬되지 않은 컨테이너 (Unordered Containers)

평균적인 경우 더 빠른 조회를 위해 해시 테이블을 사용합니다:

#include <unordered_map>

std::unordered_map<std::string, int> scores;
scores["player1"] = 100;            // 삽입: 평균 O(1)
scores["player2"] = 200;
std::cout << scores["player1"];    // 접근: 평균 O(1)

적절한 컨테이너 선택하기

  • vector: 빠른 임의 접근
  • list: 중간에 빈번한 삽입이 필요한 경우
  • map/set: 정렬된 데이터가 필요한 경우
  • unordered_map: 조회 속도가 중요하고 순서가 상관없는 경우

직접 해보기

#include <iostream>
#include <string>
#include "GradeManager.h"

using namespace std;

int main() {
    // 세 명의 학생에 대한 입력 읽기
    string name1, name2, name3;
    int grade1, grade2, grade3;
    
    cin >> name1;
    cin >> grade1;
    cin >> name2;
    cin >> grade2;
    cin >> name3;
    cin >> grade3;
    
    // TODO: GradeManager 객체 생성
    
    // TODO: 세 명의 학생을 모두 GradeManager에 추가
    
    // TODO: "Roster (insertion order):"를 출력하고 printRoster() 호출
    
    // TODO: "Grades (alphabetical):"를 출력하고 printGrades() 호출
    
    // TODO: "Unique grades:"를 출력하고 printUniqueGrades() 호출
    
    // TODO: 두 번째 학생의 성적을 조회하고 "<name>'s grade: <grade>" 출력
    
    return 0;
}
quiz icon실력 점검

이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.

객체 지향 프로그래밍의 모든 레슨