[C++] 다익스트라(Dijkstra)
·
IT/알고리즘
다익스트라(Dijkstra) 알고리즘은 그래프에서 특정 지점에서 모든 노드를 지나는 최단 거리를 구할 때 사용하는 알고리즘이다. 이때 그래프가 다음 특성을 가질 때 사용 가능하다. 모든 Edge의 비용이 양수여야 한다. 다익스트라의 시간 복잡도는 O(E * log V)이다. 다익스트라 자료구조 먼저, 그래프를 표현하기 위해서 인접 리스트 자료구조를 사용한다. 인접 리스트의 인덱스는 Start 노드이며, 각 인덱스에 해당하는 요소는 (End 노드, 가중치)이다. 만약 양방향 그래프의 경우 이방향에 대해 저장해줘야 한다. 추가로 최단 거리 배열이 필요하다. 이것은 다익스트라 원리를 구현하기 위해 필요한 자료구조이다. 처음에는 무한대에 가까운 Dummy 값으로 초기화해준다. (시작 노드는 0으로 초기화) 또한..
[C++] 위상 정렬 (Topological Sort)
·
IT/알고리즘
위상 정렬(Topological Sort)은 사이클이 없는 방향 그래프에서 노드 순서를 찾는 알고리즘이다. 이때 그래프에 사이클이 존재하면 안되며 시간 복잡도는 O(V + E)이다. 위상 정렬에서는 항상 유일한 값으로 정렬되지 않는다는 특징이 있다. 위상 정렬 자료구조 가장 먼저 위상 정렬을 위한 자료구조를 생성한다. 그래프를 나타내는 인접 리스트 자료구조를 사용한다. 이째, 위상 정렬을 위해선 진입 차수 배열이 하나 필요하다. 진입 차수 배열 초기값은 모두 0으로 설정한 뒤, 인접 리스트를 수행하면서 해당하는 노드의 값을 1씩 증가시킨다. 그리고 위상 정렬을 결과를 저장할 배열을 하나 선언한다. 또한 진입 차수가 0인 노드를 선택해야 하기 때문에, 위 노드들을 저장할 큐가 필요하다 따라서 필요한 자료구..
[C++] Union-Find
·
IT/알고리즘
Union-Find 정의 유니온 파인드(Union-Find)는 여러 노드에 대해 특정 2개의 노드를 연결해 1개의 집합으로 묶는 처리를 의미한다. Union은 집합으로 묶기 기능, Find는 노드가 속한 집합 탐색 기능으로 구성된 알고리즘이다. Union-Find의 처리 방식은 다음과 같다. Union-Find 동작 원리 Union-Find 동작 원리는 아래와 같은 순서를 가진다. 모든 노드들에 대해 1차원 int 배열을 선언하여 자신의 index를 저장한다. 처음에는 모든 노드가 연결되어 있지 않기 때문에 각 노드가 대표 노드가 된다. 2개의 노드에 대해 각각의 대표 노드를 찾아 연결하는 Union 연산을 수행한다. Union(1, 4)의 경우, 4번 노드의 대표 노드를 1번 대표 노드로 변경해준다. ..
[C++] 그래프(Graph)
·
IT/알고리즘
이 포스터에선 그래프와 관련된 기본적인 알고리즘을 소개하도록 하겠다. 그렇다면 그래프(Graph)가 무엇인가? 그래프(Graph) 그래프는 노드(Node)와 간선(Edge)로 구성된 집합이다. 노드는 데이터를 표현하는 단위이고 간선은 노드를 연결한다. 그래프는 여러 알고리즘에서 많이 사용되는 자료구조이다. 그래프 알고리즘 그래프 자료구조를 활용한 대표적인 알고리즘은 다음과 같다. 유니온 파인드: 그래프에 사이클이 존재하는지 판별하는 알고리즘 위상 정렬: 그래프를 선형 정렬한다. 사이클이 없는 방향 그래프에서 사용한다. 다익스트라: 시작점을 기준으로 모든 노드를 방문하는 최소 비용을 구한다. (음수 간선 포함 X) 벨만-포드: 시작점을 기준으로 모든 노드를 방문하는 최소 비용을 구한다. (음수 간선 포함 ..
[C++] 유클리드 호제법 (최대 공약수 & 최대 공배수)
·
IT/알고리즘
이 포스터에선 유클리드 호제법에 대해 알아보도록 하겠다. 유클리드 호제법은 두 수 A와 B에 대해 최대 공약수를 구할 때 사용된다. 앞으로 A와 B의 최대 공약수는 GCD(A, B)로 가정하겠다. GCD(A, B) 수학적 정의 2개의 자연수 A, B에 대해서 A를 B로 나눈 나머지를 r이라 하면 (단 A > B), A와 B의 최대공약수는 B와 r의 최대공약수와 같다. 이 성질에 따라, B를 r로 나눈 나머지 r0를 구하고, 다시 r을 r0로 나눈 나머지를 구하는 과정을 반복하여 나머지가 0이 되었을 때 나누는 수가 A와 B의 최대공약수이다. GCD(A, B) 코드 정의 A % B == 0이면 B를 가지고, A % B != 0이면 GCD(B, A % B)를 수행한다. 즉, 나머지가 0이 될 때의 B가 최대..
[C++] 오일러 피 (서로소)
·
IT/알고리즘
이 포스터에선 오일러 피에 대해 알아보도록 하겠다. 먼저, 오일러 피가 무엇인지 살펴보도록 하자. 오일러 피 함수 P[N]은 다음과 같이 정의된다. P[N] = [1, N] 범위에서 N과 서로소인 자연수의 개수 (1와 N 포함) 오일러 피 함수의 증명 과정을 공부해야 완벽하게 이해할 수 있지만 이 포스터에서는 구현 부분만 알아보도록 할 것이다. 오일러 피 함수 원리 오일러 피는 이전 포스터에서 봤던 에라토스테네스의 체와 매우 유사하다. 1. 사전에 미리 N개의 int 배열 메모리를 할당한다. 2. 각 배열의 값은 K로 초기화한다. 3. K의 배수에 해당하는 자리마다 P[K] = P[K] - P[K] / K을 수행한다. 4. K를 2부터 N까지 해당하는 범위에 대해 3번을 반복한다. 과정은 매우 간단하다...
[C++] 소수 구하기 (에라토스테네스의 체)
·
IT/알고리즘
이 포스터에선 소수 구하기에 대해 알아보겠다. Naive한 방식과 에라토스테네스의 체 방식을 코드로 살펴보도록하자. 먼저, 소수(Prime Number)란 무엇인가? 양의 양수가 1 혹은 자기 자신 밖에 없는 1보다 큰 자연수를 의미한다. 예를 들어, 8의 약수는 1, 2, 4, 8이기 때문에 소수가 아니다. 7의 약수는 1, 7이기 때문에 소수이다. Naive 방식 코드 bool is_prime_number(int n) { if (n N; // 초기화 for (int i = 2; i
[C++] 머지 정렬 (Merge Sort)
·
IT/알고리즘
원리 머지 정렬(Merge Search)의 정렬 원리는 다음과 같다. 머지 정렬은 퀵 정렬과 마찬가지로 Divide and Conquer 방식을 사용한다. 따라서 재귀 함수를 사용하며, 종료 구문이 필요하다. 시간 복잡도는 O(n * Log n)에 해당한다. 새로운 메모리를 할당해야 한다는 단점이 있다. 하지만 Instructions 처리 과정에서 원본 메모리 값은 유지된다는 점에서 Stable Sort 기법으로 분류된다. C++ algorithm 헤더 파일의 stable_sort 함수가 머지 정렬을 사용한다. 코드 #include #include #define VEC_SIZE 10 using namespace std; /* 아이디어 1. 배열을 절반으로 나누기 (크기가 1 이하가 되면 멈추기) 2. 쪼..
[C++] 퀵 정렬 (Quick Sort)
·
IT/알고리즘
원리 퀵 정렬 (Quick Sort) 정렬 원리는 다음과 같다. 퀵 정렬은 Divide and Conquer 방식을 사용한다. 따라서 재귀 함수를 사용하며, 종료 구문이 필요하다. 시간 복잡도는 O(n * Log n)에 해당한다. 효율적인 정렬 방법으로, 현재 가장 많이 사용하는 방식이다. 동일 메모리 값이 실시간으로 처리되는 점에서 Unstable Sort 기법으로 분류된다. C++ algorithm 헤더 파일의 sort 함수가 퀵 정렬을 사용한다. 코드 #include #include using namespace std; void swap(int& a, int& b) { int temp = a; a = b; b = temp; } void quick_sort(vector& arr, int s, int ..
[C++] 버블 정렬 (Bubble Sort)
·
IT/알고리즘
원리 버블 정렬(Bubble Search)는 직관적인 알고리즘이다. 정렬 원리는 다음과 같다. 버블 정렬은 선택 정렬과 동일하게 이중 반복문을 통해 완전 탐색을 수행한다. 따라서 시간 복잡도는 O(n^2)에 해당한다. (선택 정렬과 차이점은 Swap 횟수로, 버블 정렬이 좀 더 Swap이 자주 일어남) 비효율적인 정렬 방법으로, 작은 크기일 때 사용한다. 코드 #include #include using namespace std; void swap(int& a, int& b) { int temp = a; a = b; b = temp; } void bubble_sort(vector& arr) { int min_idx; for (int i = 0; i < arr.size(); i++) { min_idx = i..