C++
string
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main() {
// ===== 1. 생성 & 초기화 =====
string s1 = "Hello";
string s2("World");
string s3(5, 'A'); // "AAAAA"
string s4 = s1 + " " + s2; // "Hello World"
cout << "[생성] " << s1 << " | " << s2 << " | " << s3 << " | " << s4 << "\n\n";
// ===== 2. 크기 & 접근 =====
string s = "hello";
cout << "[크기] size=" << s.size() << ", empty=" << boolalpha << s.empty() << "\n";
cout << "[접근] s[1]=" << s[1] << ", at(1)=" << s.at(1)
<< ", front=" << s.front() << ", back=" << s.back() << "\n\n";
// ===== 3. 수정 =====
s.push_back('!'); // hello!
s.pop_back(); // hello
s.insert(1, "123"); // h123ello
s.erase(1, 3); // hello
s.replace(0, 2, "yo"); // yollo
cout << "[수정] " << s << "\n\n";
s.clear(); // ""
cout << "[clear 후 empty] " << s.empty() << "\n\n";
// ===== 4. 부분 문자열 & 찾기 =====
string t = "abracadabra";
cout << "[substr] " << t.substr(0, 3) << "\n"; // "abr"
cout << "[find] cad 위치: " << t.find("cad") << "\n"; // 4
cout << "[rfind] 마지막 a: " << t.rfind("a") << "\n"; // 10
cout << "[find_first_of] cd 중 첫 등장: " << t.find_first_of("cd") << "\n"; // 4
cout << "[find_last_of] 마지막 a 위치: " << t.find_last_of("a") << "\n\n"; // 10
// ===== 5. 비교 =====
string a = "apple", b = "banana";
cout << "[비교] (a==b)=" << (a==b) << ", (a<b)=" << (a<b)
<< ", compare=" << a.compare(b) << "\n\n";
// ===== 6. 변환 =====
string numStr = "12345";
int x = stoi(numStr);
double y = stod("3.14");
string z = to_string(9876);
cout << "[변환] stoi=" << x << ", stod=" << y << ", to_string=" << z << "\n\n";
// ===== 7. 순회 =====
string loopStr = "hello";
cout << "[순회 - 복사] ";
for (auto c : loopStr) cout << c << " "; cout << "\n";
cout << "[순회 - 참조] ";
for (auto& c : loopStr) c = toupper(c);
cout << loopStr << "\n\n";
// ===== 8. 알고리즘 =====
string alg = " trim me ";
reverse(alg.begin(), alg.end());
cout << "[reverse] " << alg << "\n";
sort(alg.begin(), alg.end());
cout << "[sort] " << alg << "\n";
// 공백 제거 (앞뒤만)
string trimStr = " abc def ";
trimStr.erase(0, trimStr.find_first_not_of(' '));
trimStr.erase(trimStr.find_last_not_of(' ')+1);
cout << "[trim] '" << trimStr << "'\n";
return 0;
}
C++
복사
vector
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
int main() {
vector<int> v;
// 상태/용량 관련
cout << v.size() << "\n"; // 0
cout << boolalpha << v.empty() << "\n"; // true
v.reserve(10); // capacity 미리 확보
cout << v.capacity() << "\n";
// 삽입/접근
v.push_back(10);
v.emplace_back(20); // in-place 생성
v.insert(v.begin(), 5); // 임의 위치 삽입
if (!v.empty()) cout << v.front() << " " << v.back() << "\n"; // 5 20
cout << v[1] << " " << v.at(1) << "\n"; // 범위 체크(at)
// 수정/삭제
v[0] = 7;
v.erase(v.begin()); // 첫 원소 삭제
if (!v.empty()) v.pop_back();
// 중복 제거(정렬 + unique-erase 관용구)
v = {3,1,2,2,3,3};
sort(v.begin(), v.end()); // 1 2 2 3 3 3
v.erase(unique(v.begin(), v.end()), v.end()); // 1 2 3
// 반복/순회
for (int x : v) cout << x << " ";
// 기타
v.clear(); // 모두 삭제
v.shrink_to_fit(); // capacity 줄이기(힙 반환 시도)
}
C++
복사
pair
#include <utility>
#include <tuple>
#include <iostream>
using namespace std;
int main() {
pair<int,string> p = make_pair(1, "apple");
auto q = pair{2, string("banana")}; // C++17 class template argument deduction
cout << p.first << " " << p.second << "\n";
// 비교(사전식)
cout << boolalpha << (p < q) << "\n";
// tie / 구조적 바인딩
int id; string name;
tie(id, name) = p; // tie
auto [i, s] = q; // C++17 구조적 바인딩
}
C++
복사
map (정렬 맵, 중복 키 불가)
#include <map>
#include <iostream>
using namespace std;
int main() {
map<string,int> m;
// 삽입/접근
m["apple"] = 3; // 없으면 생성 후 대입
m.insert({"banana", 5});
m.emplace("cherry", 7);
m.try_emplace("date", 10); // key만 보고 생성(값 생성 비용↓)
// 조회
if (!m.empty() && m.find("banana") != m.end())
cout << m.at("banana") << "\n"; // 범위 체크 .at
cout << boolalpha << m.contains("apple") << "\n"; // C++20
// 정렬 특성 활용(lower_bound/upper_bound)
auto it = m.lower_bound("b"); // key >= "b" 중 첫 원소
if (it != m.end()) cout << it->first << "\n";
// 순회(정렬된 키 순서)
for (auto& [k, v] : m) cout << k << ":" << v << " ";
// 삭제
m.erase("apple");
if (!m.empty()) m.erase(m.begin()); // 이터레이터로 삭제
m.clear();
}
C++
복사
set (정렬 집합, 중복 불가)
#include <set>
#include <iostream>
using namespace std;
int main() {
set<int> s;
s.insert(10);
s.emplace(5);
s.insert(10); // 무시됨(중복 X)
cout << s.size() << " " << boolalpha << s.empty() << "\n";
// 조회
if (s.find(5) != s.end()) cout << "5 있음\n";
cout << s.count(10) << "\n"; // 0 또는 1
// 범위 검색
auto it = s.lower_bound(6); // >= 6
if (it != s.end()) cout << *it << "\n";
// 순회
for (int x : s) cout << x << " ";
// 삭제
s.erase(5);
if (!s.empty()) s.erase(s.begin());
s.clear();
}
C++
복사
queue (FIFO)
#include <queue>
#include <iostream>
using namespace std;
int main() {
queue<int> q;
cout << boolalpha << q.empty() << "\n"; // true
q.push(1);
q.emplace(2);
q.push(3);
// 사용 전 항상 empty() 체크
while (!q.empty()) {
cout << q.front() << " "; // 맨 앞
q.pop(); // 제거
}
// back(), size(), swap()
q.push(10); q.push(20);
if (!q.empty()) cout << q.back() << "\n"; // 맨 뒤
cout << q.size() << "\n";
}
C++
복사
deque (양쪽 입출, 임의 접근)
#include <deque>
#include <iostream>
using namespace std;
int main() {
deque<int> dq;
cout << boolalpha << dq.empty() << "\n"; // true
dq.push_back(10);
dq.push_front(20);
dq.emplace_back(30);
if (!dq.empty()) {
cout << dq.front() << " " << dq.back() << "\n"; // 20 30
cout << dq[1] << "\n"; // 임의 접근
cout << dq.at(1) << "\n"; // 범위 체크
}
dq.pop_front();
dq.pop_back();
// insert/erase (중간 삽입/삭제도 vector보다 유리)
dq.insert(dq.begin(), 99);
if (!dq.empty()) dq.erase(dq.begin());
dq.clear();
}
C++
복사
priority_queue (기본: 최대 힙)
#include <queue>
#include <vector>
#include <iostream>
using namespace std;
int main() {
// 최대 힙
priority_queue<int> pq;
cout << boolalpha << pq.empty() << "\n"; // true
pq.push(3);
pq.emplace(10);
pq.push(5);
// 사용 전 empty() 체크 습관화
while (!pq.empty()) {
cout << pq.top() << " "; // 가장 큰 값
pq.pop();
}
// 최소 힙
priority_queue<int, vector<int>, greater<int>> minpq;
for (int x : {7,1,4}) minpq.push(x);
if (!minpq.empty()) cout << "\nmin: " << minpq.top() << "\n";
// 사용자 정의(예: pair에서 score 큰 순)
using P = pair<int,int>; // {score, id}
struct Cmp {
bool operator()(const P& a, const P& b) const {
return a.first < b.first; // 큰 score가 먼저 나오도록(최대 힙 성향)
}
};
priority_queue<P, vector<P>, Cmp> rpq;
rpq.emplace(95, 2);
rpq.emplace(87, 5);
rpq.emplace(99, 1);
while (!rpq.empty()) {
auto [score, id] = rpq.top();
cout << score << ":" << id << " ";
rpq.pop();
}
}
C++
복사
sort 계열 알고리즘(algorithm)
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
struct Node { int a, b; };
int main() {
vector<int> v = {5,1,4,2,3};
// sort: 기본 오름차순
sort(v.begin(), v.end()); // 1 2 3 4 5
// 내림차순
sort(v.begin(), v.end(), greater<int>()); // 5 4 3 2 1
// 사용자 정의 비교
vector<Node> arr = {{1,3},{1,2},{2,1}};
sort(arr.begin(), arr.end(), [](const Node& x, const Node& y){
if (x.a != y.a) return x.a < y.a; // a 오름차순
return x.b > y.b; // a 동률이면 b 내림차순
});
// stable_sort: 같은 값의 상대적 순서 보장
stable_sort(v.begin(), v.end());
// partial_sort: 상위 k개만 정렬
int k = 3;
partial_sort(v.begin(), v.begin()+k, v.end()); // 앞 k개가 정렬된 상태
// nth_element: n번째 원소가 올 자리에 오도록(partition)
nth_element(v.begin(), v.begin()+k, v.end()); // v[k]는 정렬 기준상 정확 위치
// 이진 탐색 계열(정렬 필요)
sort(v.begin(), v.end());
bool has3 = binary_search(v.begin(), v.end(), 3);
auto itL = lower_bound(v.begin(), v.end(), 3); // 첫 >= 3
auto itU = upper_bound(v.begin(), v.end(), 3); // 첫 > 3
cout << boolalpha << has3 << " " << (itL - v.begin()) << " " << (itU - v.begin()) << "\n";
// reverse/rotate
reverse(v.begin(), v.end());
rotate(v.begin(), v.begin()+1, v.end()); // 좌회전 1칸
}
C++
복사
보너스: 컨테이너 선택 간단 가이드
•
인덱스 접근·끝 삽입/삭제가 많다: vector
•
양끝 삽입/삭제가 많다: deque
•
키-값 보관, 키 정렬 필요: map (정렬)
•
원소 집합, 정렬·범위쿼리: set / 중복 허용 multiset
•
단순 FIFO: queue
•
최댓값/최솟값을 자주 꺼낸다: priority_queue
•
정렬/이진탐색이 필요하면 먼저 sort, 그 다음 binary_search/lower_bound/upper_bound
추가적으로
map<int, priority_queue<int, vector<int>, greater<int>>> under5;
// ID 기반 점수 오름차순
map<int, priority_queue<int, vector<int>>> top5;
// ID 기반 점수 내림차순
// vector에서 중복 제거
// 1) 정렬
sort(v.begin(), v.end()); // 1 2 2 3 3 3 4
// 2) unique → 연속된 중복 원소 제거 (뒤로 밀림)
auto it = unique(v.begin(), v.end()); // [1,2,3,4, ?, ?, ?]
// 3) erase → 실제 vector 크기 줄이기
v.erase(it, v.end()); // [1,2,3,4]
// 기존 인덱스를 가지고 있으면서 정렬
vector<int> nums = {50, 20, 50, 10};
vector<pair<int,int>> vp;
for (int i = 0; i < (int)nums.size(); i++) {
vp.push_back({nums[i], i});
}
sort(vp.begin(), vp.end()); // (값, 인덱스) 기준 정렬됨 오름차순
sort(vp.begin(), vp.end(), greater<pair<int,int>>()); // 내림차순
// 배열에서 숫자가 나온 만큼을 frequency로 정리
map<int,int> freq; // key: 값, value: 빈도수
for (int x : nums) {
freq[x]++;
}
C++
복사
Python
1. heapq 사용법 (최소 힙 기반)
import heapq
# 기본 힙(최소 힙)
h = []
heapq.heappush(h, 3)
heapq.heappush(h, 1)
heapq.heappush(h, 5)
print(h[0]) # 최소값 조회
print(heapq.heappop(h)) # 최소값 꺼내기
# 리스트를 힙으로 변환
arr = [7, 2, 9, 1]
heapq.heapify(arr)
# 최대 힙(음수 변환)
maxh = []
for x in [3,1,5]:
heapq.heappush(maxh, -x)
print(-heapq.heappop(maxh)) # 최대값
# 상위/하위 k개
nums = [9,1,5,3,7]
print(heapq.nsmallest(3, nums)) # [1,3,5]
print(heapq.nlargest(2, nums)) # [9,7]
Python
복사
2. deque 사용법 (양쪽 O(1) 삽입/삭제)
from collections import deque
dq = deque([1,2,3])
# 양쪽 삽입/삭제
dq.append(4) # 오른쪽에 추가
dq.appendleft(0) # 왼쪽에 추가
dq.pop() # 오른쪽 제거
dq.popleft() # 왼쪽 제거
# 기타
dq.rotate(1) # 오른쪽으로 회전
dq.rotate(-2) # 왼쪽으로 회전
print(len(dq), dq[0], dq[-1])
for i in range(m):
for k in range(n):
if visited[i][k] or grid[i][k] == "0":
continue
queue = deque([(i, k)])
visited[i][k] = True
num += 1
while queue:
x, y = queue.popleft()
for dx, dy in dirs:
nx, ny = x + dx, y + dy
if 0 <= nx < m and 0 <= ny < n:
if not visited[nx][ny] and grid[nx][ny] == "1":
visited[nx][ny] = True
queue.append((nx, ny))
Python
복사
3. 문자열(str) 관련 패턴
s = " Hello, Python 3.10! "
# 길이/접근
len(s), s[0], s[-1], s[2:7],
s[::-1] # 문자열 뒤집기
# 공백 제거
s.strip(), s.lstrip(), s.rstrip()
# 분할/결합
"John,Doe".split(",")
" ".join(["a","b","c"])
# 찾기/검사
s.find("Python"), s.count("o")
s.startswith("He"), s.endswith("!")
# 치환
"2025-09-23".replace("-", "/")
# 대소문자
"heLLo".lower(), "heLLo".upper(), "abc".title()
# 포맷팅
f"Alice got {97.5:.1f}"
"{:,.0f}".format(1234567)
# 판별
"123".isdigit(), "abc".isalpha(), "a1".isalnum()
Python
복사
SQL
SQL 기본 – CRUD
SQL은 보통 데이터를 다루는 네 가지 기본 동작(CRUD)을 기반으로 합니다.
작업 | 명령어 | 설명 |
C(Create) | INSERT | 데이터 추가 |
R(Read) | SELECT | 데이터 조회 |
U(Update) | UPDATE | 데이터 수정 |
D(Delete) | DELETE | 데이터 삭제 |
•
(1) CREATE – 데이터 삽입
CREATE TABLE Employee (
empId INT PRIMARY KEY, -- PK는 자동으로 NOT NULL
name VARCHAR(50) NOT NULL, -- 이름은 반드시 값이 있어야 함
salary INT NULL -- 급여는 없어도 됨 (기본은 NULL 허용)
);
CREATE TABLE Bonus (
empId INT, -- Employee.empId를 참조
bonus INT default 0, -- 보너스 금액 디폴트 0
FOREIGN KEY (empId) REFERENCES Employee(empId)
);
-- students 테이블에 한 줄 삽입
INSERT INTO students (id, name, age, major)
VALUES (1, 'Alice', 20, 'Computer Science');
-- 여러 줄 삽입
INSERT INTO students (id, name, age, major)
VALUES
(2, 'Bob', 22, 'Physics'),
(3, 'Charlie', 21, 'Mathematics');
-- 일부 삽입
-- name만 넣고, 나머지는 NULL
INSERT INTO Employee (name)
VALUES ('Charlie');
SQL
복사
•
(2) READ – 데이터 조회 (SELECT)
-- 모든 열 조회
SELECT * FROM students;
-- 특정 열만 조회
SELECT name, age FROM students;
-- 별칭 사용
SELECT name AS student_name, age AS student_age
FROM students;
SQL
복사
•
(3) UPDATE – 데이터 수정
-- 조건에 맞는 데이터 수정
UPDATE students
SET age = 23
WHERE id = 2;
--
UPDATE Salary as s
SET s.sex = CASE s.sex
WHEN 'f' THEN 'm'
WHEN 'm' THEN 'f'
ELSE s.sex
END;
SQL
복사
•
(4) DELETE – 데이터 삭제
-- 조건에 맞는 데이터 삭제
DELETE FROM students
WHERE id = 3;
-- 전체 삭제 (주의!)
DELETE FROM students;
SQL
복사
SELECT 문 – 조건/정렬/제한
-- 조건 필터링
SELECT * FROM students
WHERE age >= 21;
-- 정렬
SELECT * FROM students
ORDER BY age DESC;
-- 제한 (MySQL, PostgreSQL)
SELECT * FROM students
ORDER BY age DESC
LIMIT 2;
SQL
복사
WHERE 절 – 다양한 조건
-- 비교 연산
SELECT * FROM students WHERE age = 20;
SELECT * FROM students WHERE age BETWEEN 20 AND 22;
-- 문자열 패턴
SELECT * FROM students WHERE name LIKE 'A%'; -- A로 시작
SELECT * FROM students WHERE name LIKE '%e'; -- e로 끝남
-- 집합
SELECT * FROM students WHERE major IN ('Physics', 'Mathematics');
-- 논리 연산
SELECT * FROM students WHERE age > 20 AND major = 'Physics';
SQL
복사
GROUP BY – 집계 함수와 함께
GROUP BY는 데이터를 그룹화하고 집계 함수를 적용할 때 사용합니다.
주요 집계 함수:
•
COUNT(*) : 개수
•
SUM(col) : 합
•
AVG(col) : 평균
•
MIN(col) / MAX(col) : 최소, 최대
-- 전공별 학생 수
SELECT major, COUNT(*) AS num_students
FROM students
GROUP BY major;
-- 전공별 평균 나이
SELECT major, AVG(age) AS avg_age
FROM students
GROUP BY major;
SQL
복사
HAVING – 그룹 조건
WHERE는 그룹핑 이전 조건,
HAVING은 그룹핑 이후 조건에 사용합니다.
-- 전공별 학생 수가 1명 이상인 전공만
SELECT major, COUNT(*) AS num_students
FROM students
GROUP BY major
HAVING COUNT(*) >= 2;
-- 전공별 평균 나이가 21 이상인 전공만
SELECT major, AVG(age) AS avg_age
FROM students
GROUP BY major
HAVING AVG(age) >= 21;
SQL
복사
예제 (종합)
-- 21세 이상인 학생들 중 전공별 평균 나이를 구하고,
-- 그 평균이 22 이상인 전공만, 평균 나이 내림차순 정렬
SELECT major, AVG(age) AS avg_age
FROM students
WHERE age >= 21
GROUP BY major
HAVING AVG(age) >= 22
ORDER BY avg_age DESC;
SQL
복사
•
CRUD = Insert / Select / Update / Delete
•
WHERE: 그룹화 전 조건
•
GROUP BY: 그룹 단위 집계
•
HAVING: 그룹화 후 조건
JOIN
•
테이블 A와 B가 있을 때, 공통된 **키(column)**를 기준으로 데이터를 합치는 것
•
보통 PRIMARY KEY와 FOREIGN KEY 관계에서 자주 사용됨
예시 테이블:
students
+----+--------+------+
| id | name | age |
+----+--------+------+
| 1 | Alice | 20 |
| 2 | Bob | 22 |
| 3 | Charlie| 21 |
+----+--------+------+
enrollments
+----+-----------+----------+
| id | student_id| course |
+----+-----------+----------+
| 1 | 1 | Math |
| 2 | 1 | Physics |
| 3 | 2 | Chemistry|
+----+-----------+----------+
Plain Text
복사
1. INNER JOIN (교집합)
•
양쪽 테이블에서 조건에 일치하는 데이터만 가져옴
SELECT s.name, e.course
FROM students s
INNER JOIN enrollments e
ON s.id = e.student_id;
SQL
복사
결과:
Alice Math
Alice Physics
Bob Chemistry
Plain Text
복사
2. LEFT JOIN (왼쪽 테이블 기준)
•
왼쪽 테이블(students)의 모든 행을 가져오고,
•
오른쪽(enrollments)에서 일치하는 값이 있으면 붙이고, 없으면 NULL
SELECT s.name, e.course
FROM students s
LEFT JOIN enrollments e
ON s.id = e.student_id;
SQL
복사
결과:
Alice Math
Alice Physics
Bob Chemistry
Charlie NULL
Plain Text
복사
3. RIGHT JOIN (오른쪽 테이블 기준)
•
오른쪽 테이블(enrollments)의 모든 행을 가져오고,
•
왼쪽(students)에서 일치하는 값이 없으면 NULL
SELECT s.name, e.course
FROM students s
RIGHT JOIN enrollments e
ON s.id = e.student_id;
SQL
복사
결과:
Alice Math
Alice Physics
Bob Chemistry
Plain Text
복사
(만약 enrollments에 학생 없는 데이터가 있으면 name = NULL)
4. FULL OUTER JOIN (합집합)
•
두 테이블을 모두 포함
•
어느 한쪽에만 있어도 결과에 나타남
•
MySQL은 직접 지원하지 않고 UNION으로 흉내냄
SELECT s.name, e.course
FROM students s
FULL OUTER JOIN enrollments e
ON s.id = e.student_id;
SQL
복사
5. CROSS JOIN (카르테시안 곱)
•
두 테이블의 모든 조합을 생성 (조건 X)
SELECT s.name, e.course
FROM students s
CROSS JOIN enrollments e;
SQL
복사
결과 = 학생 수 × 수강행 수 (매우 커질 수 있음)
6. SELF JOIN (자기 자신과 JOIN)
•
같은 테이블을 두 번 불러와서 JOIN
-- 같은 나이인 학생끼리 묶기
SELECT a.name AS student1, b.name AS student2
FROM students a
JOIN students b
ON a.age = b.age AND a.id < b.id;
SQL
복사
7. JOIN + GROUP BY (응용)
JOIN은 보통 집계와 함께 많이 씁니다.
-- 각 학생이 수강하는 과목 수
SELECT s.name, COUNT(e.course) AS num_courses
FROM students s
LEFT JOIN enrollments e
ON s.id = e.student_id
GROUP BY s.name;
SQL
복사
•
INNER JOIN: 공통된 행만
•
LEFT JOIN: 왼쪽 전부 + 매칭
•
RIGHT JOIN: 오른쪽 전부 + 매칭
•
FULL OUTER JOIN: 둘 다 전부
•
CROSS JOIN: 모든 조합
•
SELF JOIN: 자기 자신과 JOIN
Additionally
•
ID를 할 때 Distinct를 써야함에 주의