설 연휴 2/16~18 + 대학교 졸업식 2/19
라이브러리 활용
표준 라이브러리 구성
입출력, 문자열 처리, 컨테이너, 알고리즘, 기타 유틸리티
표준 라이브러리 사용
헤더 포함
# include <파일_이름>
iostream - cout
string - 문자열(C++ 컴파일러에 따라 필요 여부 다름)
#include <iostream>
#include <string>
using namespace std;
int main() {
string str1("Hello");
cout << str1 << endl;
cout << str1[0] << endl;
cout << str1[1] << endl;
cout << str1[2] << endl;
cout << str1[3] << endl;
cout << str1[4] << endl;
return 0;
}
Hello
H
e
l
l
o
length, size - 문자열 길이 구하기
#include <iostream>
#include <string>
using namespace std;
int main() {
string str1("Hello");
cout << str1 << endl;
cout << str1.length() << endl;
cout << str1.size() << endl;
return 0;
}
Hello
5
5
empty - 빈 문자열 검사하기
#include <iostream>
#include <string>
using namespace std;
int main() {
string str1("");
cout << str1 << endl;
cout << std::boolalpha;
cout << str1.empty() << endl; // true 또는 false 출력
return 0;
}
true
append - 문자열 추가하기
#include <iostream>
#include <string>
using namespace std;
int main() {
string str1("Hello");
str1.append(" World!");
cout << str1 << endl;
string str2("Hello");
str2.append(" World!", 6, 1);
cout << str2 << endl;
return 0;
}
Hello World!
Hello!
find - 문자열 찾기
#include <iostream>
#include <string>
using namespace std;
void check_found(string::size_type n) {
if (n == string::npos) {
cout << "not found" << endl;
}
else {
cout << "found index: " << n << endl;
}
}
int main() {
string::size_type n;
string str = "This is an example of a standard string.";
// 문자열 시작 지점부터 "example" 탐색
n = str.find("example");
check_found(n);
// 문자열 시작 지점부터 "is" 탐색
n = str.find("is");
check_found(n);
// 문자열 내 index 위치 4부터 "is" 탐색
n = str.find("is", 4);
check_found(n);
// 문자열 시작 지점부터 'h' 탐색
n = str.find('h');
check_found(n);
// 문자열 시작 지점부터 'k' 탐색
n = str.find('k');
check_found(n);
return 0;
}
found index: 11
found index: 2
found index: 5
found index: 1
not found
compare - 문자열 비교하기
#include <iostream>
#include <string>
using namespace std;
void compare_result(int result) {
if (result == 0) {
cout << result << " = 두 문자열이 같음" << endl;
}
else if (result > 0) {
cout << result << " = 대상 문자열이 더 길거나 일치하지 않는 첫 번째 문자가 더 큼" << endl;
}
else if (result < 0) {
cout << result << " = 대상 문자열이 더 짧거나 일치하지 않는 첫 번째 문자가 더 작음" << endl;
}
}
int main() {
// 1. s1, s2 문자열이 같을 때
string s1 = "Hello";
string s2 = "Hello";
int result = s1.compare(s2);
compare_result(result);
// 2. s1 문자열의 길이가 더 짧을 때
s1 = "Hello";
s2 = "Hello World";
result = s1.compare(s2);
compare_result(result);
// 3. s1 문자열의 첫 번째 문자가 알파벳 순서상 먼저 나올 때
s1 = "cat";
s2 = "dog";
result = s1.compare(s2);
compare_result(result);
// 4. s1 문자열의 길이가 더 클 때
s1 = "Hello World";
s2 = "Hello";
result = s1.compare(s2);
compare_result(result);
// 5. s1 문자열의 길이가 더 짧지만,
// 일치하지 않는 첫 번째 문자가 알파벳 순서상 늦게 나올 때
s1 = "cat";
s2 = "apple";
result = s1.compare(s2);
compare_result(result);
return 0;
}
0 = 두 문자열이 같음
-1 = 대상 문자열이 더 짧거나 일치하지 않는 첫 번째 문자가 더 작음
-1 = 대상 문자열이 더 짧거나 일치하지 않는 첫 번째 문자가 더 작음
1 = 대상 문자열이 더 길거나 일치하지 않는 첫 번째 문자가 더 큼
1 = 대상 문자열이 더 길거나 일치하지 않는 첫 번째 문자가 더 큼
replace - 문자열 교체하기
#include <iostream>
#include <string>
using namespace std;
int main() {
string str = "Hello, world!";
cout << "Original string: " << str << std::endl;
// 문자열 일부분을 교체
str.replace(7, 5, "C++");
cout << "Replaced string: " << str << endl;
return 0;
}
Original string: Hello, world!
Replaced string: Hello, C++!
wstring - 와이드 문자열
#include <iostream>
#include <string>
using namespace std;
int main() {
// setlocale 함수를 사용하여 프로그램의 로케일(locale)을 변경
// LC_ALL은 '모든 로케일' 설정으로 지정을 의미함
setlocale(LC_ALL, "");
// wstring을 사용하여 유니코드 문자열을 초기화
// L 접두사를 붙여 유니코드 문자열임을 나타냄
wstring korString = L"안녕하세요";
// wcout을 사용하여 유니코드 문자열을 출력
// wcout은 유니코드 문자열을 출력하기 위한 wide character 출력 스트림
wcout << korString << endl;
return 0;
}
안녕하세요
파일 시스템
데이터를 저장하고 관리하는 체계 의미
파일 입출력: 파일에다가 뭘 쓰거나, 파일에 쓰인 것을 읽는 것
파일 시스템: 운영체제가 하는 일을 하는 것(새파일 생성, 지우기, 이름 변경 등)
절대 경로: 최상위 디렉터리인 루트에서 내가 원하는 파일까지의 전체 경로
상대 경로: 현재 위치를 기준으로 한 경로
파일 시스템 라이브러리 활용
#include <iostream>
#include <string>
#include <filesystem> // 파일 시스템 헤더 파일
#include <fstream> // 파일 입출력 헤더 파일
using namespace std;
namespace fs = filesystem;
int main() {
// 1. 디렉터리 생성
fs::create_directories("MyDirectory");
// 2. 파일 생성 및 쓰기
ofstream outFile("MyDirectory/myFile.txt");
outFile << "Hello, FileSystem Library!" << endl;
outFile.close();
// 3. 디렉터리 내의 파일 확인
cout << "Files in MyDirectory:\n";
for (const fs::directory_entry& entry : fs::directory_iterator("MyDirectory")) {
if (entry.is_regular_file()) {
cout << entry.path().filename() << endl;
}
}
// 4. 파일 읽기
ifstream inFile("MyDirectory/myFile.txt");
string line;
while (getline(inFile, line)) {
cout << line << endl;
}
inFile.close();
// 5. 파일 및 디렉터리 삭제
fs::remove_all("MyDirectory");
return 0;
}
Files in MyDirectory:
"myFile.txt"
Hello, FileSystem Library!
인헨스드 for문은 컨테이너의 모든 요소를 간단하게 순회하는 문법
난수: 정의된 범위에서 무작위로 추출된 임의의 수
기타 유용한 함수
random
#include <iostream>
#include <random>
using namespace std;
int main() {
mt19937_64 mt_rand;
for (int i = 0; i < 10; i++) {
cout << mt_rand() << endl;
}
return 0;
}
14514284786278117030
4620546740167642908
13109570281517897720
17462938647148434322
355488278567739596
7469126240319926998
4635995468481642529
418970542659199878
9604170989252516556
6358044926049913402
시드값으로 난수 생성
#include <iostream>
#include <random>
#include <chrono>
using namespace std;
int main() {
// 시드값 사용
auto curTime = chrono::system_clock::now();
auto duration = curTime.time_since_epoch();
auto millis = chrono::duration_cast<chrono::milliseconds>(duration).count();
mt19937_64 mt_rand(millis);
for (int i = 0; i < 10; i++) {
cout << mt_rand() << endl;
}
return 0;
}
16844689945438387676
6469006369704289924
623049299764690398
3462591277359121517
18335651871874979387
4478737152284376692
12625768926443555605
13694133195895371591
1313246467480176690
15198019475067663565
하드웨어 엔트로피로 난수 생성
#include <iostream>
#include <random>
using namespace std;
int main() {
random_device rng;
for (int i = 0; i < 10; i++) {
auto result = rng();
cout << result << endl;
}
return 0;
}
683169620
2956381839
3916975418
2272013009
2957365260
1026822047
973348425
1429476582
4001400505
29693926
과제: 난수 생성 기능 이용 주사위 구현
프로그램 요구사항:
프로그램 실행하면, 1~6 사이 숫자 중 하나 랜덤 출력
방법은 자유
조건: LLM 금지
#include <iostream>
#include <random>
using namespace std;
int main() {
default_random_engine generator;
uniform_int_distribution <int> distribution(1, 6);
for (int i = 0; i < 1; ++i)
std::cout << distribution(generator) << "\n";
return 0;
}
cout << mt_rand() % 6 + 1 << endl;
수학 함수
#include <iostream>
#include <cmath>
#include <numbers>
using namespace std;
int main() {
double x = 2;
double y = 3;
cout << "x = " << x << ", " << "y = " << y << endl;
cout << "pow(x, y) = " << pow(x, y) << endl;
cout << "sqrt(x) = " << sqrt(x) << endl;
cout << "log(x) = " << log(x) << endl;
cout << endl;
x = 2.847;
y = -3.234;
cout << "x = " << x << ", " << "y = " << y << endl;
cout << "ceil(x) = " << ceil(x) << ", ceil(y) = " << ceil(y) << endl;
cout << "floor(x) = " << floor(x) << ", floor(y) = " << floor(y) << endl;
cout << "round(x) = " << round(x) << ", round(y) = " << round(y) << endl;
cout << "abs(x) = " << abs(x) << ", abs(y) = " << abs(y) << endl;
cout << endl;
cout << "PI = " << numbers::pi << endl;
cout << "sin(PI/3) = " << sin(numbers::pi / 3) << endl;
cout << "cos(PI/3) = " << cos(numbers::pi / 3) << endl;
cout << "tan(PI/3) = " << tan(numbers::pi / 3) << endl;
return 0;
}
x = 2, y = 3
pow(x, y) = 8
sqrt(x) = 1.41421
log(x) = 0.693147
x = 2.847, y = -3.234
ceil(x) = 3, ceil(y) = -3
floor(x) = 2, floor(y) = -4
round(x) = 3, round(y) = -3
abs(x) = 2.847, abs(y) = 3.234
PI = 3.14159
sin(PI/3) = 0.866025
cos(PI/3) = 0.5
tan(PI/3) = 1.73205
복사 함수
얕은 복사: 주솟값을 복사
깊은 복사: 실제 값을 새로운 메모리 공간에 복사
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
// 사람 정보를 담는 구조체
struct Person {
string name; // 이름
int age; // 나이
float height; // 키
float weight; // 몸무게
};
// 벡터에 저장된 사람 정보 출력 함수
void print_person_all(vector<Person>& vec) {
for (vector<Person>::iterator it = vec.begin(); it != vec.end(); it++) {
cout << "이름: " << it->name << "\t > " << "나이: " << it->age << ", " << "키: " << it->height << ", " << "몸무게: " << it->weight << endl;
}
}
int main() {
// Person 구조체 배열 생성
Person p[5] = {
{"Brain", 24, 180, 70},
{"Jessica", 22, 165, 55},
{"James", 30, 170, 65},
{"Tom", 12, 155, 46},
{"Mary", 18, 172, 62}
};
// from_vector에 Person 배열 순서대로 넣기
vector<Person> from_vector;
from_vector.push_back(p[0]);
from_vector.push_back(p[1]);
from_vector.push_back(p[2]);
from_vector.push_back(p[3]);
from_vector.push_back(p[4]);
// from_vector 출력
cout << "-----from_vector-----" << endl;
print_person_all(from_vector);
cout << endl;
// to_vector에 from_vector의 원소들 "깊은 복사" 수행
vector<Person> to_vector;
copy(from_vector.begin(), from_vector.end(), back_inserter(to_vector));
// 복사 후, to_vector 출력
cout << "-----to_vector-----" << endl;
print_person_all(to_vector);
cout << endl;
// from_vector의 첫 번째 요소 수정
from_vector[0].name = "Chris";
from_vector[0].age = 5;
from_vector[0].height = 110;
from_vector[0].weight = 20;
// 수정 후, from_vector 출력
cout << "-----from_vector-----" << endl;
print_person_all(from_vector);
cout << endl;
// to_vector 출력
cout << "-----to_vector-----" << endl;
print_person_all(to_vector);
cout << endl;
return 0;
}
-----from_vector-----
이름: Brain > 나이: 24, 키: 180, 몸무게: 70
이름: Jessica > 나이: 22, 키: 165, 몸무게: 55
이름: James > 나이: 30, 키: 170, 몸무게: 65
이름: Tom > 나이: 12, 키: 155, 몸무게: 46
이름: Mary > 나이: 18, 키: 172, 몸무게: 62
-----to_vector-----
이름: Brain > 나이: 24, 키: 180, 몸무게: 70
이름: Jessica > 나이: 22, 키: 165, 몸무게: 55
이름: James > 나이: 30, 키: 170, 몸무게: 65
이름: Tom > 나이: 12, 키: 155, 몸무게: 46
이름: Mary > 나이: 18, 키: 172, 몸무게: 62
-----from_vector-----
이름: Chris > 나이: 5, 키: 110, 몸무게: 20
이름: Jessica > 나이: 22, 키: 165, 몸무게: 55
이름: James > 나이: 30, 키: 170, 몸무게: 65
이름: Tom > 나이: 12, 키: 155, 몸무게: 46
이름: Mary > 나이: 18, 키: 172, 몸무게: 62
-----to_vector-----
이름: Brain > 나이: 24, 키: 180, 몸무게: 70
이름: Jessica > 나이: 22, 키: 165, 몸무게: 55
이름: James > 나이: 30, 키: 170, 몸무게: 65
이름: Tom > 나이: 12, 키: 155, 몸무게: 46
이름: Mary > 나이: 18, 키: 172, 몸무게: 62
컨테이너: 같은 타입의 여러 객체를 저장할 수 있는 묶음 단위의 데이터 구조
반복자(이터레이터): 객체지향 프로그래밍에서 배열 같은 컨테이너 내부 원소들을 순회하는 객체
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> vec; // 벡터 컨테이너 vec 선언
vec.push_back(0); // vec에 원소 추가
vec.push_back(1);
vec.push_back(2);
vec.push_back(3);
vec.push_back(4);
// 반복자 it 선언과 vec의 시작 위치로 초기화
vector<int>::iterator it = vec.begin();
cout << *it << endl; // vec에 저장된 원소 출력
cout << *(it + 1) << endl;
cout << *(it + 2) << endl;
cout << *(it + 3) << endl;
cout << *(it + 4) << endl;
return 0;
}
0
1
2
3
4
#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;
}
0
1
2
3
4
순차 컨테이너: 데이터가 순서대로 삽입되는 컨테이너
연관 컨테이너: 데이터가 오름차순/내림차순처럼 미리 정의된 순서로 삽입되는 컨테이너.
연관 컨테이너 안에 있는 원소들은 언제나 정렬된 상태를 유지
컨테이너 어댑터: 순차, 연관 컨테이너와 다르게 특별한 자료 구조를 표현한 컨태이너,
배열 size
컨테이너가 메모리에서 차지하는 크기가 아닌 원소를 저장할 수 있는 개수를 반환
배열 컨테이너 활용
#include <iostream>
#include <array>
using namespace std;
int main() {
// 크기가 5인 std::array 생성
array<int, 5> myArray;
// 배열 초기화
myArray = { 1, 2, 3, 4, 5 };
// 배열 출력
cout << "배열 출력: ";
for (int i = 0; i < 5; i++) {
cout << myArray[i] << " ";
}
cout << endl;
// 배열 크기 출력
cout << "배열 크기: " << myArray.size() << endl;
// 배열의 첫 번째 요소 출력
cout << "첫 번째 요소: " << myArray[0] << endl;
// 배열의 두 번째 요소 변경
myArray[1] = 10;
// 변경된 배열 출력
cout << "변경된 배열: ";
for (int i = 0; i < 5; i++) {
cout << myArray[i] << " ";
}
cout << endl;
return 0;
}
배열 출력: 1 2 3 4 5
배열 크기: 5
첫 번째 요소: 1
변경된 배열: 1 10 3 4 5
벡터 컨테이너의 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(0);
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); // vec[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;
}
원본
벡터 내 원소 개수 : 5
0 10 20 30 40
---------------------
insert 결과
벡터 내 원소 개수 : 6
0 10 20 25 30 40
---------------------
erase 결과
벡터 내 원소 개수 : 5
0 10 20 30 40
---------------------
리스트
연결 리스트는 데이터가 노드라 불리는 개별 객체로 구성
각 노드는 다음 노드를 가리키는 포인터를 포함
#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;
}
리스트 출력: 0 1 2 3 4
삭제 후 리스트 출력: 1 2 3
리스트 크기: 3
리스트가 비었는가? 아니오
벡터
원소에 자주 접근하고 수정해야할 때에 주로 사용
리스트
삽입과 삭제가 빈번할 때 유용
덱
여러 개의 메모리 블록을 나눠 저장하는 것이 특징
저장할 공간이 부족하면 새로 메모리 블록을 만들어 연결
#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;
}
deque 출력: 0 1 2 3 4
삭제 후 deque 출력: 1 2 3
deque 크기: 3
deque이 비었는가? 아니오
deque 첫 번째 원소: 1
deque 마지막 원소: 3
| 특징 | std::deque | std::vector |
| 메모리 할당 방식 | 메모리의 재할당이 자주 발생하지 않음 | 메모리의 재할당이 발생할 수 있음 |
| 원소 삽입과 삭제 | 양쪽 끝에서 O(1)의 시간 복잡도로 수행 | 끝에서 O(1)의 시간 복잡도로 수행, 중간에서 O(n)의 시간 복잡도로 수행 |
| 원소 접근 | O(1)의 시간 복잡도로 수행 | O(1)의 시간 복잡도로 수행 |
시간복잡도
알고리즘이나 프로그램의 실행 시간이 어느 정도인지 나타낸느 용어
빅 오 표기법을 사용해 입력 크기에 대한 함수로 나타냄
| O(1) | 상수 시간 | 증가 없음 | n이 커져도 실행 시간 일정 | 배열 인덱스 접근 |
| O(log n) | 로그 시간 | 매우 느리게 증가 | 절반씩 줄이며 탐색 | 이진 탐색 |
| O(n) | 선형 시간 | 비례 증가 | n개를 한 번씩 확인 | 단순 반복문 |
| O(n log n) | 선형 로그 | 선형보다 조금 빠름 | 분할 + 정렬 | merge sort |
| O(n²) | 이차 시간 | 급격히 증가 | 이중 반복문 | bubble sort |
| O(n³) | 삼차 시간 | 매우 느림 | 삼중 반복문 | 3중 루프 |
| O(2ⁿ) | 지수 시간 | 폭발적 증가 | 모든 경우 탐색 | 부분집합 탐색 |
| O(n!) | 팩토리얼 | 최악 | 모든 순열 탐색 | 외판원 문제(완전탐색) |
세트
고유한 값을 정렬된 순서로 저장
#include <iostream>
#include <set>
using namespace std;
int main() {
set<int> mySet;
// 값 삽입
mySet.insert(5);
mySet.insert(2);
mySet.insert(8);
// 값 5가 세트에 있는지 확인
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;
}
5는 set에 저장되어 있음
2 5 8
set 크기: 3
멀티 세트
중복된 값을 저장
(일 반 set에선 중복된 값 허용X)
#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;
// 멀티 세트를 순회하며 값 출력
for (auto it = myMultiset.begin(); it != myMultiset.end(); ++it) {
cout << *it << " ";
}
cout << endl;
// 멀티 세트의 크기 출력
int size = myMultiset.size();
cout << "multiset 크기: " << size << endl;
return 0;
}
저장되어 있는 5의 갯수: 2
2 5 5
multiset 크기: 3
맵
키-값 쌍을 저장하는 연관 컨테이너
각 키는 고유해야 하며 키를 기준으로 정렬된 순서로 저장됨
#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;
// 특정 키에 해당하는 값 검색
auto it = scores.find("Bob");
if (it != scores.end()) {
cout << "Bob의 점수 검색 결과: " << it->second << endl;
}
else {
cout << "Bob의 점수는 저장되어 있지 않음" << endl;
}
cout << endl;
// 특정 키에 해당하는 키-값 제거
scores.erase("Bob"); //Bob 정보 제거
// 맵 크기 출력
cout << "Bob 정보 제거 후, map 크기: " << scores.size() << endl << endl;
// 맵을 순회하며 모든 키와 값 출력
cout << "---map 모든 원소 출력---" << endl;
for (const auto& pair : scores) {
cout << pair.first << ": " << pair.second << endl;
}
return 0;
}
map 크기: 3
Bob의 점수 검색 결과: 85
Bob 정보 제거 후, map 크기: 2
---map 모든 원소 출력---
Jane: 90
Tom: 70
멀티맵
중복 값 허용
같은 키로 여러 값 저장 가능
특징: 중복 키 저장, 자동 정렬, 이진트리 탐색
#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 << "multimap 크기: " << scores.size() << endl;
// 특정 키에 해당하는 원소의 개수 구하기
int count = scores.count("Bob");
cout << "저장되어 있는 Bob 점수의 갯수: " << count << endl;
// 특정 키를 가진 원소의 범위 구하기
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 << " ";
}
cout << endl;
}
else {
cout << "Bob의 점수는 저장되어 있지 않음" << endl;
}
cout << endl;
// 특정 키에 해당하는 모든 원소 삭제
scores.erase("Bob"); //Bob 정보 제거
// 멀티 맵의 크기 출력
cout << "Bob 정보 제거 후, multimap 크기: " << scores.size() << endl << endl;
// 멀티 맵을 순회하며 모든 키와 값 출력
cout << "---multimap 모든 원소 출력---" << endl;
for (const auto& pair : scores) {
cout << pair.first << ": " << pair.second << endl;
}
return 0;
}
multimap 크기: 4
저장되어 있는 Bob 점수의 갯수: 2
Bob의 모든 점수: 85 100
Bob 정보 제거 후, multimap 크기: 2
---multimap 모든 원소 출력---
Jane: 90
Tom: 70
컨테이너 어댑터
다른 컨테이너를 기반으로 새로운 기능을 제공하는 컨테이너
스택
자료 구조 구현하는 데 사용
데이터를 차례대로 쌓고 가장 마지막에 넣은 데이터를 가장 먼저 꺼냄
후입선출 LIFO
#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;
// 스택에서 데이터 제거(맨 위쪽 데이터 꺼내기)
myStack.pop();
cout << "맨 위 요소 제거 후, 새로운 맨 위 요소: " << myStack.top()
<< endl;
// 스택의 크기(데이터 개수) 확인
cout << "스택 크기: " << myStack.size() << endl;
// 스택이 비었는지 확인
if (myStack.empty()) {
cout << "스택이 비었습니다." << endl;
}
else {
cout << "스택은 비어 있지 않습니다." << endl;
}
return 0;
}
맨 위 요소: 3
맨 위 요소 제거 후, 새로운 맨 위 요소: 2
스택 크기: 2
스택은 비어 있지 않습니다.
스택의 이유 및 목적
함수 호출 관리, 데잍처 임시 저장, 역순 처리, 재귀 알고리즘, 컴퓨터 아키텍처, 컴파일러와 언어 구현
큐
내부적으로 덱 컨테이너 사용
큐에서 값을 꺼낸 후 맨 앞의 값을 확인하면 변함
FIFO
데이터의 순서를 보장하고 특히 FIFO 특성 덕에 먼저 들어온 데이터가 먼저 처리되야하는 상황에서 효과적
다음과 같은 작업에서 사용
작업 대기열, 이벤트 처리, 멀티스레딩 환경에서 동기화, 너비 우선 탐색, 캐시 구현
#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; // front
cout << "큐의 맨 뒤: " << myQueue.back() << endl; // back
// 꺼내기
myQueue.pop();
cout << "pop 후 맨 앞: " << myQueue.front() << endl; // pop 후 front
cout << "pop 후 맨 뒤: " << myQueue.back() << endl; // pop 후 back
// 비었는지 확인하기
cout << "큐가 비어 있나요? " << (myQueue.empty() ? "네" : "아니오") << endl;
// 크기 구하기
cout << "큐의 크기: " << myQueue.size() << endl;
return 0;
}
큐의 맨 앞: 1
큐의 맨 뒤: 3
pop 후 맨 앞: 2
pop 후 맨 뒤: 3
큐가 비어 있나요? 아니오
큐의 크기: 2
알고리즘
코드의 복잡도를 줄이고 효율성을 높일 수 있으며 다양한 작업을 단순화하고 최적화함
정렬, 검색, 변환, 반복자, 집계
정렬: 어떤 기준으로 가지런히 줄지어 늘어서게 하는 것
ㄴ퀵 정렬: 평균적으로 매우 빠른 수행 속도, n개의 데이터를 정렬한다고 할 때 최악의 경우 O(n**2)번의 비교를 수행하지만 평균적으로 O(n log n)번의 비교를 수행
오름차순 정렬
내림차순 정렬
사용자 정의 기준 정렬
안정 정렬: 같은 원소가 정렬 후에도 원본의 순서와 일치
불안정 정렬: 같은 원소가 정렬 후에는 원본의 순서와 일치하지 않음
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
using namespace std;
struct Person {
string name; // 이름
int age; // 나이
float height; // 키
float weight; // 몸무게
};
void print_preson_all(vector<Person>& vec) {
for (vector<Person>::iterator it = vec.begin(); it != vec.end(); it++) {
cout << "이름: " << it->name << "\t > " << "나이: " << it->age << ", " << "키: " << it->height << ", " << "몸무게: " << it->weight << endl;
}
}
// Person 구조체의 나이 비교(첫 번째 인자의 나이가 작으면 true)
bool compare(const Person& lhs, const Person& rhs) {
return lhs.age < rhs.age;
}
int main() {
Person p[5] = {
{"Brain", 24, 180, 70},
{"Jessica", 22, 165, 55},
{"James", 30, 170, 65},
{"Tom", 12, 155, 46},
{"Mary", 18, 172, 62}
};
vector<Person> vec;
vec.push_back(p[0]);
vec.push_back(p[1]);
vec.push_back(p[2]);
vec.push_back(p[3]);
vec.push_back(p[4]);
cout << "-----정렬 전-----" << endl;
print_preson_all(vec);
cout << endl;
// 사용자 정의 기준으로 정렬
sort(vec.begin(), vec.end(), compare);
cout << "-----정렬 후-----" << endl;
print_preson_all(vec);
return 0;
}
-----정렬 전-----
이름: Brain > 나이: 24, 키: 180, 몸무게: 70
이름: Jessica > 나이: 22, 키: 165, 몸무게: 55
이름: James > 나이: 30, 키: 170, 몸무게: 65
이름: Tom > 나이: 12, 키: 155, 몸무게: 46
이름: Mary > 나이: 18, 키: 172, 몸무게: 62
-----정렬 후-----
이름: Tom > 나이: 12, 키: 155, 몸무게: 46
이름: Mary > 나이: 18, 키: 172, 몸무게: 62
이름: Jessica > 나이: 22, 키: 165, 몸무게: 55
이름: Brain > 나이: 24, 키: 180, 몸무게: 70
이름: James > 나이: 30, 키: 170, 몸무게: 65
찾기
순차 컨테이너에서 원하는 값을 찾는 함수
find 함수는 first_last 범위에서 value와 일치하는 첫 번째 원소를 가리키는 반복자를 반환함
만약 일치하는 원소를 못 찾으면 last를 반환함
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main() {
vector<int> numbers = { 1, 2, 3, 4, 5 };
cout << "찾고 싶은 숫자를 입력하세요: ";
int target;
cin >> target;
// 입력받은 숫자를 찾아서 해당 위치를 반환
vector<int>::iterator it = find(numbers.begin(), numbers.end(), target);
if (it != numbers.end()) {
cout << "찾은 위치: " << distance(numbers.begin(), it) << endl;
}
else {
cout << "찾을 수 없음" << endl;
}
return 0;
}
찾고 싶은 숫자를 입력하세요: 5
찾은 위치: 4
이진탐색
std::binary-search: 정렬된 범위에서 특정 값을 이진 탐색으로 찾는 함수
탐색 범위를 반으로 나눠 범위를 좁혀 가는 방식으로 동작하는 알고리즘
대상 컨테이너가 정렬되어 있어야 함
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main() {
// 정렬되지 않은 벡터
vector<int> numbers = { 8, 3, 1, 7, 4, 5, 9, 2, 6 };
// 정렬 수행
sort(numbers.begin(), numbers.end());
// 사용자에게 숫자 입력 받기
int target;
cout << "컨테이너에서 검색하고 싶은 숫자를 입력해보세요: ";
cin >> target;
// 이진 탐색
bool found = binary_search(numbers.begin(), numbers.end(), target);
if (found) {
cout << "찾았습니다." << endl;
}
else {
cout << "저장되어 있지 않습니다." << endl;
}
return 0;
}
컨테이너에서 검색하고 싶은 숫자를 입력해보세요: 3
찾았습니다.
https://www.w3schools.com/cpp/cpp_algorithms.asp
W3Schools.com
W3Schools offers free online tutorials, references and exercises in all the major languages of the web. Covering popular subjects like HTML, CSS, JavaScript, Python, SQL, Java, and many, many more.
www.w3schools.com
'로보테크AI' 카테고리의 다른 글
| 융합_로보테크 AI 자율주행 로봇 개발자 과정-26/02/24[Arduino] (0) | 2026.02.24 |
|---|---|
| 융합_로보테크 AI 자율주행 로봇 개발자 과정-26/02/23[PyQt] (0) | 2026.02.23 |
| 융합_로보테크 AI 자율주행 로봇 개발자 과정-26/02/13 (0) | 2026.02.13 |
| 융합_로보테크 AI 자율주행 로봇 개발자 과정-26/02/12 (0) | 2026.02.12 |
| 융합_로보테크 AI 자율주행 로봇 개발자 과정-26/02/11 (0) | 2026.02.11 |