이 글에서는 B-트리(B-Tree)를 이용해 정렬된 순서(sorted sequence)를 얻는 방법을 살펴봅니다. B-트리는 하나의 노드가 여러 개의 자식을 가질 수 있는 n진 트리(n-ary tree)입니다. 정렬된 순서를 얻으려면 먼저 B-트리를 생성한 뒤 숫자들을 차례대로 삽입하면 됩니다. 여기서 사용하는 B-트리는 한 노드가 최대 5개의 데이터를 저장할 수 있으며, 요소 수가 이 값을 초과하면 노드를 분할(split)하여 새로운 레벨을 형성합니다. 각 노드가 최대 5개 정도의 적은 수의 요소만 가지기 때문에, 노드 내부의
오일러 회로(Euler Circuit)를 이해하려면 먼저 오일러 경로(Euler Path)의 개념을 알아야 합니다. 오일러 경로란 그래프의 모든 정점을 정확히 한 번씩 방문할 수 있는 경로를 의미합니다. 단, 간선은 여러 번 사용할 수 있습니다. 오일러 회로는 오일러 경로의 특수한 형태로, 경로의 시작 정점과 끝 정점이 서로 연결되어 있는 경우를 말합니다.그래프에 오일러 회로가 존재하는지 판별하려면 다음 두 가지 조건을 만족해야 합니다.그래프는 반드시 연결 그래프(Connected Graph)여야 합니다.무방향 그래프에서 모든 정점
오일러 경로(Eulerian Path)는 그래프의 모든 간선을 정확히 한 번씩만 통과하면서 전체 그래프를 탐색할 수 있는 경로를 말합니다. 이때 정점은 여러 번 거쳐 가더라도 문제가 되지 않습니다. 오일러 회로(Eulerian Circuit)는 오일러 경로의 한 종류로, 경로의 시작 정점과 끝 정점이 서로 연결되어 출발점으로 돌아올 수 있는 특수한 형태입니다. 무방향 그래프에 오일러 경로가 존재하는지 판별하려면 다음 조건들을 확인해야 합니다. 그래프는 반드시 연결 그래프여야 합니다. 모든 정점의 차수(degree)가 짝수라면
오일러 경로(Euler Path)란 그래프의 모든 간선을 정확히 한 번씩 지나갈 수 있는 경로를 말합니다. 이때 정점(vertex)은 여러 번 다시 방문해도 무방합니다. 또한 오일러 회로(Euler Circuit)를 포함하는 그래프 역시 오일러 경로를 가지므로 함께 고려 대상이 됩니다.유향 그래프(directed graph)에 오일러 경로가 존재하는지 확인하려면 아래 세 가지 조건을 모두 검사해야 합니다.진출 차수(out-degree)가 진입 차수(in-degree)보다 정확히 1 큰 정점이 단 하나만 존재해야 합니다. (진입 차수
이 글에서는 C++ 프로그램을 사용해 리눅스 환경에서 파일을 수정 시간 기준으로 정렬하여 나열하는 방법을 살펴봅니다. 가장 최근에 수정된 파일부터 가장 오래된 파일까지, 또는 그 반대 순서로도 손쉽게 확인할 수 있습니다.방법은 매우 간단합니다. 리눅스 셸 명령어를 활용하면 원하는 순서대로 파일 목록을 얻을 수 있습니다. ls -l 명령어는 모든 파일을 상세 정보와 함께 출력하며, 여기에 정렬 옵션을 추가하면 됩니다. -t 옵션은 파일을 수정 시간 기준으로 정렬하고, -r 옵션을 함께 사용하면 정렬 순서가 역순으로 바뀝니다.정리하면
문자열의 문자들은 다양한 순서로 배열할 수 있습니다. 이번 글에서는 주어진 문자열로 만들 수 있는 순열(permutation)의 개수를 계산하는 방법을 알아보겠습니다. 순열 개수의 기본 원리 예를 들어 abc라는 문자열은 세 개의 서로 다른 문자로 이루어져 있으므로 3! = 6가지 방법으로 배열할 수 있습니다. 일반적으로 n개의 문자로 이루어진 문자열은 n!가지의 순열을 가질 수 있습니다. 그러나 aab처럼 같은 문자가 여러 번 등장하는 경우에는 상황이 달라집니다. 단순히 3! = 6이라고 계산하면 실제 고유한 순열보다 많은
템플릿(Template)은 특정 데이터 타입에 의존하지 않고 코드를 작성하는 일반화 프로그래밍(Generic Programming)의 핵심 기반입니다.템플릿은 범용 클래스나 함수를 만들기 위한 하나의 설계도이자 공식입니다. C++ STL의 반복자(iterator), 알고리즘(algorithm) 등 주요 라이브러리 컨테이너들이 모두 이 템플릿 개념을 바탕으로 개발되었습니다.예를 들어 vector 컨테이너는 단 하나의 정의만 존재하지만, vector<int>, vector<string>처럼 서로 다른 타입의 vec
C++에서 템플릿(template)은 일반화된 함수와 클래스를 작성하기 위해 사용되는 강력한 기능입니다. 템플릿을 활용하면 int, char, float 같은 기본 타입은 물론, 사용자가 직접 정의한 타입까지 하나의 코드로 처리할 수 있습니다.하지만 때로는 특정 타입에 대해서만 다르게 동작해야 하는 경우가 있습니다. 이럴 때 사용하는 것이 바로 템플릿 특수화(Template Specialization)입니다. 템플릿 특수화를 사용하면 다양한 타입을 처리하는 범용 템플릿은 그대로 유지하면서, 특정 타입에 한해서만 별도의 동작을 정의할
행렬식으로 삼각형 넓이 구하기이번 글에서는 2차원 좌표 공간에서 행렬식(determinant)을 활용해 삼각형의 넓이를 구하는 방법을 알아보겠습니다. 삼각형을 이루는 세 점의 좌표를 하나의 행렬에 배치하는데, 첫 번째 열에는 x값, 두 번째 열에는 y값을 넣고 세 번째 열에는 모두 1을 채웁니다. 그다음 이 행렬의 행렬식을 계산하면 되는데, 삼각형의 넓이는 행렬식 값의 절반이 됩니다. 만약 행렬식이 음수로 나오더라도 단순히 절댓값을 취해 주면 됩니다.$$Area\:=\:absolute\:of\begin{pmatrix}\frac{1}
이 글에서는 하나의 자연수를 자신보다 작은 수들의 합으로 표현하는 방법이 총 몇 가지인지 구하는 C++ 프로그램을 다룹니다. 이는 조합론에서 말하는 분할(partition)의 개수를 세는 문제와 같습니다. 예를 들어 4는 3+1, 2+2, 2+1+1, 1+1+1+1의 네 가지 방법으로 표현할 수 있습니다. 프로그램의 동작 방식은 다음과 같습니다. 숫자 n을 입력받으면 n 자체를 첫 번째 분할로 놓고, 뒤쪽 요소부터 1씩 줄여가며 새로운 분할을 만들어 냅니다. 새로운 분할이 하나 생성될 때마다 카운터를 증가시키고, 모든 요소가 1로
개요이 글에서는 C++을 사용해 정수의 각 자릿수를 확대하여 출력하는 방법을 알아봅니다. 여기서 말하는 확대란 실제 숫자 대신 # 같은 다른 문자를 활용해 훨씬 큰 형태로 숫자를 그려내는 것을 의미합니다.핵심 로직은 생각보다 단순합니다. 먼저 0부터 9까지 각 숫자를 5×5 크기의 문자 패턴으로 하나씩 정의한 뒤, 입력받은 정수를 문자열로 변환하고 각 자릿수에 해당하는 패턴을 순서대로 화면에 출력하면 됩니다.동작 원리프로그램은 크게 세 부분으로 구성됩니다.1. 숫자별 출력 함수print_zero()부터 print_nine()까지 총
경쟁 프로그래밍이나 코딩 테스트에서는 문제를 정확하고 빠르게 푸는 능력만큼이나 코드를 짧은 시간 안에 작성하는 능력도 중요합니다. 이 글에서는 작성 시간을 줄이고 코드 효율을 높여 주는 실용적인 C++ 트릭들을 하나씩 소개합니다. 1. % 연산자 없이 홀수·짝수 판별하기 비트 AND 연산(&)을 활용하면 나머지 연산자 없이도 홀짝을 판별할 수 있습니다. 모든 홀수는 최하위 비트(LSb)가 1이므로, 숫자와 1을 AND 연산한 결과가 0이 아니면 홀수, 0이면 짝수입니다. if ((n & 1) != 0) { // 홀수
C++에는 정의되지 않은 동작(Undefined Behavior, UB)이라 불리는 위험한 상황들이 존재합니다. 이는 표준에서 명확한 동작을 규정하지 않기 때문에, 컴파일러나 실행 환경에 따라 결과가 달라지거나 프로그램이 비정상 종료될 수 있습니다. C++를 다양한 목적으로 활용하려는 개발자라면 이러한 UB 사례들을 반드시 숙지하고 코드에서 피해야 합니다.아래에서는 실제로 정의되지 않은 동작을 유발하는 대표적인 코드 예제와 그 결과를 살펴보겠습니다.1. 0으로 나누기 (Divide by Zero)정수를 0으로 나누는 연산은 C++
C++에는 객체가 특정 클래스 타입의 인스턴스인지 직접 판별할 수 있는 내장 연산자가 없습니다. 반면 Java에서는 instanceof 연산자를 통해 이러한 기능을 간편하게 사용할 수 있습니다. C++11에서는 is_base_of<Base, T>라는 타입 트레이트가 도입되었습니다. 이는 컴파일 시점에 한 클래스가 다른 클래스의 기반(base) 클래스인지 여부를 검사하지만, 실제 객체 인스턴스가 해당 타입으로 변환 가능한지까지는 확인해 주지 않습니다. Java의 instanceof와 가장 유사한 동작을 구현하려면 dynam
C++에서 실수(부동소수점) 값을 미리 정해둔 소수점 자릿수까지만 출력해야 하는 경우가 자주 있습니다. 이럴 때 setprecision 조작자(manipulator)를 cout과 함께 사용하면 손쉽게 해결할 수 있습니다. setprecision은 iomanip 헤더 파일에 정의되어 있으므로, 사용하기 전에 반드시 #include <iomanip>을 추가해야 합니다. 예제 코드 #include <iostream> #include <iomanip> using namespace std; int main(
C++에서는 inline 키워드를 함수에 적용할 수 있습니다. 그리고 C++17부터는 이 개념이 확장되어 인라인 변수(inline variable)가 새롭게 도입되었습니다.인라인 변수는 여러 개의 번역 단위(translation unit)에서 정의될 수 있으며, 이때도 ODR(One Definition Rule, 단일 정의 규칙)을 준수합니다. 같은 변수가 여러 번 정의되더라도 컴파일러가 최종 프로그램에서 이를 하나의 객체로 병합해 주기 때문입니다.C++17 이전의 한계점C++17 이전 버전에서는 클래스 내부에서 정적(static)
C++에는 잘 알려지지 않았지만 활용도가 매우 높은 기능과 트릭이 많이 숨어 있습니다. 이런 기법들을 미리 익혀 두면 경쟁 프로그래밍 대회나 실무 개발에서 코드 작성 시간을 크게 단축할 수 있습니다. 지금부터 실전에서 바로 써먹을 수 있는 C++의 숨겨진 기능들을 하나씩 살펴보겠습니다. % 연산자 없이 홀수·짝수 판별하기 비트 AND(&) 연산을 이용하면 나머지 연산자 없이도 홀수와 짝수를 구분할 수 있습니다. 모든 홀수는 최하위 비트(LSB)가 1이므로, 숫자를 1과 AND 연산했을 때 결과가 0이 아니면 홀수, 0이면
C++에서 부동 소수점(floating point) 숫자는 일반적으로 4바이트(float) 또는 8바이트(double) 크기로 저장됩니다. 따라서 무한히 긴 소수를 모두 담을 수 없고, 제한된 개수의 유효 숫자만 보관할 수 있습니다.예를 들어 1/3 = 0.333333...처럼 소수점 이하가 무한히 이어지는 수가 있다고 가정해 봅시다. 이 값을 부동 소수점 변수에 저장하면 컴퓨터는 유한한 유효 숫자만 기록합니다. C++의 기본 정밀도(precision)는 유효 숫자 6자리이므로, 별도 설정 없이는 보통 소수점 이하 6자리까지만 표시
공유 메모리란 무엇인가?공유 메모리(Shared Memory)는 두 개 이상의 프로세스가 함께 접근하여 사용하는 메모리 공간을 의미합니다. 그렇다면 왜 굳이 메모리를 공유하거나 별도의 통신 수단이 필요할까요?각 프로세스는 독립적인 주소 공간(address space)을 가지고 있기 때문입니다. 한 프로세스가 자신의 주소 공간에 있는 정보를 다른 프로세스에 전달하려면 반드시 IPC(Inter-Process Communication, 프로세스 간 통신) 기법을 사용해야만 합니다. IPC는 부모-자식 관계처럼 서로 관련 있는 프로세스 사
공유 메모리(shared memory)가 이미 있는데도 굳이 메시지 큐(message queue)가 필요할까요? 그 이유는 여러 가지가 있습니다. 이해하기 쉽도록 몇 가지 항목으로 나누어 살펴보겠습니다.공유 메모리 대신 메시지 큐를 사용하는 이유메시지 큐에서는 한 프로세스가 메시지를 수신하면 해당 메시지는 다른 어떤 프로세스에게도 더 이상 제공되지 않습니다. 반면 공유 메모리의 데이터는 여러 프로세스가 동시에 접근할 수 있습니다.작은 크기의 메시지 형식으로 통신하고자 할 때 적합합니다.공유 메모리는 여러 프로세스가 동시에 통신할 경