컨테이너와 반복자(array, vector, list, deque, set, multiset, map, multimap, stack, queue)

윤이령·2026년 4월 23일

컨테이너

  • 같은 타입의 여러 객체를 저장할 수 있는 묶음 단위의 데이터 구조

반복자

  • 객체지향 프로그래밍에서 배열 같은 컨테이너의 내부 원소들을 순회하는 객체
  • 컨테이너 안의 한 원소를 가리키는 위치
  • 포인터처럼 동작하도록 만든 객체라서 역참조가 가능하다

반복자 역참조 연산

#include <iostream>
#include <vector>

using namespace std;

int main() {
	vector<int> vec;
	vec.push_back(0);
	vec.push_back(2);

	vector<int>::iterator it = vec.begin();
	cout << *it << endl; //0
	cout << *(it + 1) << endl; //2

	return 0;
}

반복자 증가 연산

  • begin() : 벡터의 첫번째 원소
  • end() : 벡터의 맨 마지막 원소의 바로 다음 위치 반환
#include <iostream>
#include <vector>

using namespace std;

int main() {
	vector<int> vec;
	for (int i = 0; i < 5;i++) {
		vec.push_back(i);
	}

	//반복자를 이용해 순회
	for (vector<int>::iterator it = vec.begin(); it != vec.end(); it++) {
		cout << *it << endl;
	}

	return 0;
}

정적 반복자

  • 반복자가 가르키는 원솟값을 변경할수 없음
vector<int>::const_iterator const_it = vec.cbegin();
*const_it = 100; // 값 변경 -> 에러
++const_it // 가르키는 대상 변경 -> 가능

리버스 반복자

  • 뒤에서 앞으로 이동
  • rbegin() : 가장 마지막에 저장된 위치 가르킴
  • rand() : 가장 앞에 저장된 원소에서 바로 이전 위치 가르킴
for(vector<int>::reverse_iterator it = vec.rbegin(); it != vec.rand(); it++)

순차 컨테이너

  • 순차 컨테이너 : 데이터가 순서대로 삽입되는 컨테이너
    • array, vector, list, deque

array 배열

#include <iostream>
#include <array>
using namespace std;

int main() {
	//크기가 5인 array생성
	array<int, 5> myArray;

	myArray = { 1, 2, 3, 4, 5 };

	cout << "배열 출력: ";
	for (const int& element : myArray) {
		cout << element << " "; // 1, 2, 3, 4, 5
	}
	cout << endl;

	cout << "배열 크기: " << myArray.size() << endl; // 5

	cout << "첫번째 원소: " << myArray[0] << endl; // 1

	myArray[1] = 10;

	cout << "변경된 배열: ";
	for (int i = 0; i < 5; i++) {
		cout << myArray[i] << " "; // 1 10 3, 4, 5
	}
	cout << endl;

	return 0;
}

vector 벡터

원소 추가하기

  • push_back 사용
#include <iostream>
#include <vector>
using namespace std;
int main() {
	vector<int> vec;
	vec.push_back(0);
	vec.push_back(1);
	vec.push_back(2);
	for (int i = 0; i < 3; i++) {
		cout << "vec 의 " << i + 1 << "번째 원소 : " << vec[i] << endl;
	}

	return 0;
}

insert, erase

  • insert: 한칸씩 뒤로 밀리도록 복사 저장
  • erase: 한칸씩 앞으로 당겨지도록 복사 저장
#include <iostream>
#include <vector>
using namespace std;

template<typename T>
void print_vector_all(vector<T>& vec) {
	cout << "벡터 내 원소 개수 : " << vec.size() << endl;
	for (typename vector<T>::iterator it = vec.begin(); it != vec.end(); it++) {
		cout << *it << " ";
	}
	cout << endl << "----------" << endl;
}

int main() {
	vector<int> vec;
	vec.push_back(10);
	vec.push_back(20);
	vec.push_back(30);
	vec.push_back(40);

	cout << "원본" << endl;
	print_vector_all(vec);

	vec.insert(vec.begin() + 3, 25); // vector[3] 앞에 25 추가
	cout << "insert 결과 출력" << endl;
	print_vector_all(vec);

	vec.erase(vec.begin() + 3); // vec[3] 제거
	cout << "erase 결과 출력" << endl;
	print_vector_all(vec);

	return 0;
}

list 리스트

#include <iostream>
#include <list>
using namespace std;

int main() {
	list<int> myList;
	//뒤에 값 추가
	myList.push_back(2);
	myList.push_back(3);
	myList.push_back(4);
	//앞에 값 추가
	myList.push_front(1);
	myList.push_front(0);

	cout << "리스트 출력: ";
	for (const int& value : myList) {
		cout << value << " ";
	}
	cout << endl;

	myList.pop_front();//첫번째 원소 제거
	myList.pop_back();//마지막 원소 제거

	cout << "삭제 후 리스트 출력: ";
	for (const int& value : myList) {
		cout << value << " ";
	}
	cout << endl;

	cout << "리스트 크기: " << myList.size() << endl;
	cout << "리스트가 비었는가? " << (myList.empty() ? "예" : "아니요") << endl;

	return 0;
}

벡터는 원소에 자주 접근하고 수정해야 할 때
리스트는 삽입과 삭제가 빈번할 때

deque 덱

#include <iostream>
#include <deque>
using namespace std;

int main() {
	deque<int> myDeque;

	//덱 뒤에 값 추가
	myDeque.push_back(2);
	myDeque.push_back(3);
	myDeque.push_back(4);
	//덱 앞에 값 추가
	myDeque.push_front(1);
	myDeque.push_front(0);

	cout << "deque 출력: ";
	for (const int& value : myDeque) {
		cout << value << " ";
	}
	cout << endl;

	myDeque.pop_front(); // 첫번째 덱 원소 제거
	myDeque.pop_back(); // 마지막 덱 원소 제거

	cout << "삭제 후 deque 출력: ";
	for (const int& value : myDeque) {
		cout << value << " ";
	}
	cout << endl;

	cout << "deque 크기 : " << myDeque.size() << endl;
	cout << "deque이 비어있는가? " << (myDeque.empty() ? "예" : "아니요") << endl;
	
	cout << "deque 첫번째 원소: " << myDeque.front() << endl;
	cout << "deque 마지막 원소: " << myDeque.back() << endl;

	return 0;
}

연관 컨테이너

  • 연관 컨테이너 : 데이터가 오름차순/내림차순처럼 미리 정의된 순서로 삽입되는 컨테이너. 언제나 정렬된 상태 유지
    • set, multiset, map, multimap

set 세트

  • set는 중복 허용x
  • 자동으로 정렬해줌
  • insert : 값 넣을 때
  • erase : 특정 값 제거
  • clear : 전체 제거
  • find : 특정 값 검색
#include <iostream>
#include <set>
using namespace std;

int main() {
	set<int> mySet;

	mySet.insert(5);
	mySet.insert(2);
	mySet.insert(8);

	if (mySet.find(5) != mySet.end()) {
		cout << "5는 set에 저장되어 있음" << endl;
	}

	for (auto it = mySet.begin(); it != mySet.end(); ++it) {
		cout << *it << " ";
	}
	cout << endl;
	int size = mySet.size();
	cout << "set크기 : " << size << endl;

	return 0;
}

multiset 멀티 세트

  • 중복 허용 set
#include <iostream>
#include <set>

using namespace std;

int main() {
	multiset<int> myMultiset;

	myMultiset.insert(5);
	myMultiset.insert(2);
	myMultiset.insert(5);

	int count = myMultiset.count(5);
	cout << "저장되어있는 5의 개수" << count << endl; // 2

	for (auto it = myMultiset.begin(); it != myMultiset.end(); ++it) {
		cout << *it << " "; // 2 5 5
	}
	cout << endl;

	int size = myMultiset.size();
	cout << "multiset크기: " << size << endl; // 3

	return 0;
}

map 맵

  • 키값 중복 x
#include <iostream>
#include <string>
#include <map>

using namespace std;

int main() {
	map<string, int> scores;

	//키-값 쌍 삽입
	scores.insert(make_pair("Bob", 85));
	scores.insert(make_pair("Jane", 90));
	scores.insert(make_pair("Tom", 70));

	cout << "map 크기" << scores.size() << endl; // 3

	//특정 키에 해당하는 값 검색
	auto it = scores.find("Bob");
	if (it != scores.end()) {
		cout << "Bob의 점수 검색 결과 : " << it->second << endl; // 85
	}
	else {
		cout << "Bob의 점수는 저장되어있지 않음" << endl;
	}
	cout << endl;

	//특정 키에 해당하는 키-값 제거
	scores.erase("Bob");

	cout << "Bob 정보 제거 후, map크기 : " << scores.size() << endl << endl; // 2

	cout << "---map 모든 원소 출력---" << endl;
	for (const auto& pair : scores) {
		cout << pair.first << ": " << pair.second << endl; // Jane: 90 / Tom: 70
	}
	return 0;
}

multimap 멀티 맵

  • 키값 중복 가능 -> 같은 키 여러개 가능
  • 내부적으로 키를 기준으로 정렬됨. -> 기본 오름차순
#include <iostream>
#include <string>
#include <map>

using namespace std;

int main() {
	multimap<string, int> scores;

	//키-값 쌍 삽입
	scores.insert(make_pair("Bob", 85));
	scores.insert(make_pair("Jane", 90));
	scores.insert(make_pair("Tom", 70));
	scores.insert(make_pair("Bob", 100));

	cout << "map 크기" << scores.size() << endl; // 4

	//특정 키에 해당하는 원소의 개수
	int count = scores.count("Bob");
	cout << "저장되어있는 Bob 점수의 개수 : " << count << endl; // 2

	//특정 키를 가진 원소의 범위 구하기
	auto range = scores.equal_range("Bob");
	if (range.first != scores.end()) {
		cout << "Bob의 모든 점수 : ";
		for (auto it = range.first; it != range.second; ++it) {
			cout << it->second << " "; // 85 100
		}
		cout << endl;
	}
	else {
		cout << "Bob의 점수는 저장되어있지 않음" << endl;
	}
	cout << endl;

	scores.erase("Bob");

	cout << "Bob 정보 제거 후, multimap 크기: " << scores.size() << endl; // 2

	cout << "---map 모든 원소 출력---" << endl;
	for (const auto& pair : scores) {
		cout << pair.first << ": " << pair.second << endl; // Jane: 90 / Tom: 70
	}
	return 0;
}

컨테이너 어댑터

  • 컨테이너 어댑터 : 순차, 연관 컨테이너와 다르게 특별한 자료 구조를 표현한 컨테이너
    • stack, queue

stack 스택

  • 후입 선출
#include <iostream>
#include <stack>
using namespace std;

int main() {
	stack<int> myStack;

	myStack.push(1);
	myStack.push(2);
	myStack.push(3);

	cout << "맨 위 원소: " << myStack.top() << endl; // 3

	myStack.pop();
	cout << "맨 위 원소 제거 후, 새로운 맨 위 원소: " << myStack.top() << endl; // 2

	cout << "스택 크기: " << myStack.size() << endl; // 2

	if (myStack.empty()) {
		cout << "스택이 비어있습니다." << endl;
	}
	else {
		cout << "스택은 비어있지 않습니다." << endl;
	}

	return 0;
}

queue 큐

  • 선입 선출
#include <iostream>
#include <queue>
using namespace std;

int main() {
	queue<int> myQueue;

	myQueue.push(1);
	myQueue.push(2);
	myQueue.push(3);

	cout << "큐의 맨 앞: " << myQueue.front() << endl;//1
	cout << "큐의 맨 뒤: " << myQueue.back() << endl;//3

	myQueue.pop(); // 꺼내기

	cout << "pop 후 맨앞: " << myQueue.front() << endl;//2
	cout << "pop 후 맨뒤: " << myQueue.back() << endl;//3

	cout << "큐가 비어있나요? " << (myQueue.empty() ? "Y" : "N") << endl;//N

	cout << "큐의 크기: " << myQueue.size() << endl;//2

	return 0;
}

0개의 댓글