힙(Heap)은 특별한 구조의 완전 이진 트리(Complete Binary Tree)로, 주로 우선순위 큐(Priority Queue)를 구현하는 데 사용된다. 힙은 데이터의 삽입, 삭제, 조회 등의 작업을 처리하며 힙에는최소 힙(Min-Heap)최대 힙(Max-Heap)  두 가지 타입이 있다.
  • 최소 힙(Min-Heap): 모든 부모 노드는 자식 노드보다 작거나 같다. 루트 노드가 가장 작은 값을 가진다.
  • 최대 힙(Max-Heap): 모든 부모 노드는 자식 노드보다 크거나 같다. 루트 노드가 가장 큰 값을 가잔다.

힙의 기본 개념

  • 힙은 완전 이진 트리의 형태를 가지며, 모든 레벨이 완전히 채워져야 하고, 마지막 레벨은 왼쪽부터 채워져야 한다. 완전 이진 트리는 노드가 가능한 한 왼쪽에 밀집해 있는 트리이다.

힙의 주요 연산

  1. 삽입(Insert):
    • 새 노드를 힙에 추가할 때, 먼저 트리의 마지막 레벨의 가장 왼쪽에 추가한다.
    • 추가 후에는 힙의 성질을 유지하기 위해 노드를 부모 노드와 비교하여 필요시 교환하는 작업(업힙, heapify-up)을 수행한다.
  2. 삭제(Delete):
    • 힙에서 가장 중요한 연산은 루트 노드의 삭제이다. 루트 노드는 최소 힙에서는 가장 작은 값, 최대 힙에서는 가장 큰 값을 가지고 있다.
    • 루트 노드를 삭제하면, 트리의 마지막 레벨에서 가장 오른쪽의 노드를 루트로 이동시킨다.
    • 그 다음, 힙의 성질을 유지하기 위해 "힙 속성 위반"을 해결하기 위해 노드를 자식 노드와 비교하여 필요시 교환하는 작업(다운힙, heapify-down)을 수행한다.
  3. 힙 속성 유지:
    • 힙은 삽입이나 삭제 연산 후에도 그 특성(최소 힙 또는 최대 힙)을 유지한다. 이를 위해 heapify 연산을 사용한다.

힙의 시간 복잡도

  • 삽입: O(log N) - 트리의 높이에 비례한다.
  • 삭제(루트 삭제): O(log N) - 트리의 높이에 비례한다.
  • 최소/최대값 조회: O(1) - 루트 노드를 조회한다.

힙의 구현

힙은 배열을 사용하여 구현할 수 있다. 배열에서 힙의 각 노드는 다음과 같은 인덱스 규칙을 가진다:

  • 부모 노드의 인덱스가 i일 때:
    • 왼쪽 자식 노드의 인덱스는 2 * i + 1
    • 오른쪽 자식 노드의 인덱스는 2 * i + 2
  • 자식 노드의 인덱스가 i일 때:
    • 부모 노드의 인덱스는 (i - 1) / 2 (정수 나눗셈)
    •  

다익스트라 알고리즘(Dijkstra's Algorithm)

 

다익스트라 알고리즘은 그래프에서 특정 시작 노드에서 다른 모든 노드까지의 최단 경로를 찾기 위한 알고리즘이다. 이 알고리즘은 모든 엣지가 0 이상일때 적용되며 노드와 엣지로 구성된 그래프에서 출발 노드부터 각 노드까지의 최단 거리를 계산할 때 사용된다.

  • 비음수 가중치: 다익스트라 알고리즘은 모든 엣지가 0 이상인 양수일때만 동작한다. 
  • 그리디 알고리즘: 다익스트라 알고리즘은 매 단계마다 현재까지 발견된 최단 거리를 기반으로 탐색을 진행하므로, 그리디 방식으로 최적의 해를 찾는다.

알고리즘의 작동 원리

  1. 초기화:
    • 거리 배열(dist): 출발 노드에서 각 노드까지의 최단 거리를 저장하는 배열이다. 초기에는 출발 노드의 거리를 0으로 설정하고, 나머지 노드의 거리는 무한대(INF)로 설정한다.
    • 우선순위 큐(Priority Queue): 현재까지 발견된 최단 거리 정보를 기반으로 노드를 처리하는 데 사용된다. 일반적으로 최소 힙을 사용하여 구현하며 큐에 출발 노드를 추가하고, 거리를 0으로 설정한다.
  2. 반복 과정:
    • 노드 추출: 우선순위 큐에서 거리 값이 가장 작은 노드를 추출한다. 이 노드가 현재까지 발견된 최단 거리 정보를 가진 노드이다.
    • 거리 업데이트: 현재 노드와 인접한 노드들에 대해 최단 거리를 업데이트한다. 현재 노드를 통해 각 인접 노드까지 가는 거리를 계산하고, 기존 거리보다 짧으면 거리를 갱신한다. 거리 업데이트 후, 변경된 노드를 우선순위 큐에 다시 추가한다.
      • 우선순위 큐가 비어있을 때까지 위의 과정을 반복한다. 이 때, dist 배열에는 출발 노드에서 각 노드까지의 최단 거리가 저장된다.

알고리즘의 시간 복잡도

  • 우선순위 큐를 배열로 구현: O(N^2) (노드의 수가 N일 때)
  • 우선순위 큐를 이진 힙으로 구현: O((N + E) log N) (E는 엣지의 수)

이진 힙을 사용하여 구현할때 제곱근이 사용되는 배열보다 시간복잡도가 단축된다.

 

힙 메서드 구현 (자바)

import java.util.Arrays;

public class MinHeap {
    private int[] heap;
    private int size;
    private static final int DEFAULT_CAPACITY = 10;

    public MinHeap() {
        heap = new int[DEFAULT_CAPACITY];
        size = 0;
    }

    public void insert(int value) {
        if (size == heap.length) {
            ensureCapacity();
        }
        heap[size] = value;
        size++;
        heapifyUp(size - 1);
    }

    public int delete() {
        if (size == 0) {
            throw new IllegalStateException("Heap is empty");
        }
        int root = heap[0];
        heap[0] = heap[size - 1];
        size--;
        heapifyDown(0);
        return root;
    }

    public int getMin() {
        if (size == 0) {
            throw new IllegalStateException("Heap is empty");
        }
        return heap[0];
    }

    public void heapify(int[] array) {
        heap = array;
        size = array.length;
        for (int i = (size / 2) - 1; i >= 0; i--) {
            heapifyDown(i);
        }
    }

    private void heapifyUp(int index) {
        int parent = (index - 1) / 2;
        if (index > 0 && heap[index] < heap[parent]) {
            swap(index, parent);
            heapifyUp(parent);
        }
    }

    private void heapifyDown(int index) {
        int leftChild = 2 * index + 1;
        int rightChild = 2 * index + 2;
        int smallest = index;

        if (leftChild < size && heap[leftChild] < heap[smallest]) {
            smallest = leftChild;
        }

        if (rightChild < size && heap[rightChild] < heap[smallest]) {
            smallest = rightChild;
        }

        if (smallest != index) {
            swap(index, smallest);
            heapifyDown(smallest);
        }
    }

    private void swap(int i, int j) {
        int temp = heap[i];
        heap[i] = heap[j];
        heap[j] = temp;
    }

    private void ensureCapacity() {
        heap = Arrays.copyOf(heap, heap.length * 2);
    }
}

연산별 시간 복잡도 비교

연산/자료구조스택(Stack)큐(Queue)우선순위 큐(Priority Queue)

삽입 O(1) O(1) O(log N)
삭제 O(1) O(1) O(log N)
최댓값/최솟값 얻기 O(1) O(1) O(1)

 

스택 (Stack):

  • 삽입: 스택의 맨 위에 원소를 추가하는 연산. 상수 시간 O(1) 소요
  • 삭제: 스택의 맨 위에 있는 원소를 제거하는 연산. 상수 시간 O(1) 소요
  • 최댓값/최솟값 얻기: 스택의 맨 위에 있는 원소를 조회하는 연산. 상수 시간 O(1) 소요
  1. 큐 (Queue):
    • 삽입: 큐의 뒤쪽에 원소를 추가하는 연산. 상수 시간 O(1) 소요
    • 삭제: 큐의 앞쪽에서 원소를 제거하는 연산. 상수 시간 O(1) 소요
    • 최댓값/최솟값 얻기: 큐의 앞쪽에 있는 원소를 조회하는 연산. 상수 시간 O(1) 소요
  2. 우선순위 큐 (Priority Queue):
    • 삽입: 힙에 원소를 추가하는 연산. 로그 시간 O(log N) 소요
    • 삭제: 힙에서 루트 노드를 삭제하는 연산. 로그 시간 O(log N) 소요
    • 최댓값/최솟값 얻기: 힙의 루트 노드를 조회하는 연산. 상수 시간 O(1) 소요

'자료구조 > 알고리즘 기초수학' 카테고리의 다른 글

모듈러 연산  (0) 2024.08.29
칸토어 집합  (0) 2024.08.13
행렬식  (0) 2024.08.13
피보나치 수열  (0) 2024.08.13
백트래킹 (Backtracking)  (0) 2024.08.12

모듈러 연산은 알고리즘에서 숫자의 크기를 조절하거나 특정 패턴에 찾는 데 사용된다. 

주로 해시 함수나 데이터베이스 인덱싱, 랜덤 숫자 생성에 쓰이며

정수의 나머지 연산을 기반으로 하는 연산이다. 

예를 들어, 두 정수 a와 b가 있을 때 a를 b로 나눈 나머지를 구한다.


 

 a를 b로 나누는 것을 의미하며, mod는 모듈로라고 부른다.

 

17을 5로 나누면 몫이 3이고 나머지가 2이다. 

23을 7로 나누면 몫이 3이고 나머지가 2이다.

 

모듈러 연산의 성질

 

  • 합의 성질: (a+b)mod  m=((amod  m)+(bmod  m))mod 
  • 두 수를 더한 후 모듈러 연산을 하는 것과, 각각 모듈러 연산을 한 후 더하는 값이 같다.
  • 곱셈의 성질: (a×b)mod  m=((amod  m)×(bmod  m))mod
  • 두 수를 곱한 후 모듈러 연산을 하는 것과, 각각 모듈러 연산을 한 후 곱하는 값이 같다.
  • 거듭제곱의 성질: (ak)mod  m=((amod  m)k)mod  m
  • 숫자의 거듭제곱을 모듈러 연산 후 나머지를 구하는 것과 모듈러 연산 후 거듭제곱을 하는 것이 같다.

 

'자료구조 > 알고리즘 기초수학' 카테고리의 다른 글

힙과 다익스트라  (0) 2024.09.10
칸토어 집합  (0) 2024.08.13
행렬식  (0) 2024.08.13
피보나치 수열  (0) 2024.08.13
백트래킹 (Backtracking)  (0) 2024.08.12

칸토어 집합


칸토어 집합은 단위 구간 [0,1]을 특정 방식으로 잘라서 만들어지는 집합이다.

이를 통해 만들어지는 집합은 프랙탈이라는 특성을 가진다.

 

단위 구간

모든 실수 x에 대해 0 <= x <= 1 인 값들을 포함한다.

구간의 길이는 1이다. 구간의 끝점 1에서 시작점 0을 뺀 값으로 계산되며, 1 - 0 = 1 이 된다.

칸토어 집합을 만드는 방법

  1. 구간 [0,1] 을 만든다. 이 구간은 길이가 1인 직선의 구간이다.
  2. 이 구간의 가운데 1/3을 제거한다.
                                                                                                =

남은 구간.

 

  1.  두 구간에서 각각 가운데 1/3을 다시 제거한다.
  2. 이 과정을 무한히 반복한다

칸토어 집합의 성질

  1. 길이: 처음에는 길이가 1인 단위 구간에서 시작하지만, 각 단계마다 제거되는 부분의 총 길이의 합은 무한히 커진다. 결과적으로, 칸토어 집합의 총 길이는 0이다.
  2. 불연속적: 칸토어 집합은 연속적이지 않은 집합이다. 단위 구간 0, 1에서 1/3을 반복적으로 제거했을 때 그 과정에서 나머지는 점점 더 작아지며, 무한히 반복하다 보면 무수히 많은 점들로 이루어진 집합이 된다.
  3. 프랙탈: 칸토어 집합은 프랙탈의 성질을 가진다. 처음에는 전체 구간 [0,1]에서 가운데 1/3을 제거하고, 그 후에는 남은 구간들에서 다시 가운데 1/3을 제거하는 방식으로 일정한 패턴으로 구성되며 이 과정을 계속 반복하면, 각 단계의 결과가 서로서로 자기유사성을 보인다. 어떤 구간을 확대해 보면, 그 확대된 부분이 원래의 칸토어 집합과 유사한 구조를 가지고 있다.

칸토어 집합을 생성하는 과정에서 각 단계에서 계속해서 구간이 제거되지만, 제거되는 구간의 총 길이는 점점 더 작아지고, 결국에는 집합의 총 길이는 0이 된다. 하지만 여전히 내부에는 무한히 많은 점들이 남아 있다. 모래사장에 있는 모래알들을 계속해서 제거하면서도, 남아 있는 모래알들이 무한히 많고, 여전히 모래사장의 형태를 유지하는 것처럼, 칸토어 집합도 무한히 많은 점들로 구성되어 있는 것이다

'자료구조 > 알고리즘 기초수학' 카테고리의 다른 글

힙과 다익스트라  (0) 2024.09.10
모듈러 연산  (0) 2024.08.29
행렬식  (0) 2024.08.13
피보나치 수열  (0) 2024.08.13
백트래킹 (Backtracking)  (0) 2024.08.12

행렬이란?

행렬(matrix)은 숫자를 사각형 형태로 배열한 것이다.

예를 들어, 2x2 행렬은 2개의 행과 2개의 열로 이루어져 있다.

 

2x2 행렬의 예:

행렬식이란?

행렬식은 이 행렬에 대해 계산된 하나의 숫자이다.

이 숫자는 행렬의 특성과 성질을 나타낸다.

행렬식의 계산

2x2 행렬의 행렬식

 

det(행렬식) = ad - bc 

이 계산식은 대각선 원소의 곱에서 나머지 대각선 원소의 곱을 뺀 값이다.

3x3 행렬의 행렬식

 

각 원소에 대해 2x2 행렬의 행렬식을 계산한다.

소행렬을 사용하여 원래 행렬의 크기를 줄여서 계산하여 더한다

 

1. 각 원소에 대해 소행렬을 계산한다.

 

원소 a

 

원소 b

 

원소 c

 

2. 여인수를 계산하여 부호를 반영한다

 

  • 원소 a의 여인수: +a ⋅ (e⋅i−f⋅h)
  • 원소 b의 여인수: −b ⋅ (d⋅i−f⋅g)
  • 원소 c의 여인수: +c ⋅ (d⋅h−e⋅g)

3. 이 값을 모두 더하여 행렬식을 구한다

det(A )= a⋅(e⋅i−f⋅h)−b⋅(d⋅i−f⋅g)+c⋅(d⋅h−e⋅g)

 

소행렬 (Minor)

소행렬은 주어진 행렬에서 특정 원소를 제외한 부분의 행렬의 행렬식이다.

예를 들어, 3x3 행렬에서 a라는 원소가 있을 때

소행렬은 이 원소가 위치한 행과 열을 제외한 나머지 부분으로 구성된 행렬의 행렬식이다.

여인수 (Cofactor)

여인수는 소행렬의 행렬식에 원소의 위치에 따라 부호를 곱한 것이다.

여인수의 부호는 원소의 위치에 따라 결정된다

  • 위치 (i,j)(i, j)의 원소의 여인수는 (−1)i+j(-1)^{i+j}를 소행렬의 행렬식에 곱한 것이다.

행렬의 가역성 확인

행렬식이 0이 아니면, 이 행렬은 역행렬을 가진다.

  • 이 행렬을 이용해 방정식을 해결할 수 있다.
  • 행렬식이 0이면 역행렬이 없고 방정식에 유일한 해가 없거나 무한히 많다

역행렬

 

원래 행렬과 곱했을 때 항등행렬을 만드는 행렬

 

항등행렬

 

항등행렬은 대각선에만 1이 있고 나머지 원소는 모두 0인 정사각형 모양의 행렬이다.

 

  • 행렬 A와 역행렬 (행렬 A의 역수)를 곱하면 항등행렬이 된다.
  • 숫자 x의 역수는 1이 되며 이는 항등원이다. 행렬에서도 같은 개념이 적용된다. 

 

'자료구조 > 알고리즘 기초수학' 카테고리의 다른 글

모듈러 연산  (0) 2024.08.29
칸토어 집합  (0) 2024.08.13
피보나치 수열  (0) 2024.08.13
백트래킹 (Backtracking)  (0) 2024.08.12
비트마스크 (Bit Mask)  (0) 2024.08.12

피보나치 수열

피보나치 수열은 다음과 같은 규칙에 따라 정의되는 숫자들의 집합이다.

  1. 첫 두 숫자:
    • 첫 번째 숫자는 0이다.
    • 두 번째 숫자는 1이다.
  2. 다음 숫자:
    • 이후의 숫자는 항상 이전 두 숫자의 합이다.

 

피보나치 수열 예시

 

0, 1, 1, 2, 3, 5, 8, 13, 21, 34 ...

 

자기 유사성: 수열의 각 숫자는 이전 두 숫자의 합으로 정의된다. 이 수열은 매우 규칙적이며 연속적인 관계를 가지고 있다

황금 비율: 피보나치 수열의 항들의 비율은 황금 비율(약 1.618)에 가깝다. 큰 숫자들을 나누면 황금 비율에 가까워진다

황금비율

두 수의 비율이 서로의 합과 두 수 중 큰 수의 비율과 같을 때의 비율이다.

두 수 ab (a>b)의 비율이 황금비율일때 다음의 식과 같다

황금비율의 보수

황금비율의 보수는 황금비율의 자기 유사성과 연결된다.

황금비율을 가진 구조에서 보수 또한 유사한 패턴을 따른다.

피보나치 수열의 계산 방법

재귀적 계산: 수열의 각 항을 계산할 때, 이전 두 항을 더한다. 

동적 프로그래밍: 이전에 계산된 결과를 저장하고 재사용한다. 이 방법은 큰 숫자에 대해서도 빠르게 계산할 수 있다.

폐쇄형 공식: 피보나치 수열의 항을 직접 계산할 수 있는 공식이 있다. Binet's formula를 사용하면 직접 계산할 수 있다.

Binet's formula

재귀적인 계산 방법을 사용하지 않고, 피보나치 항의 주어진 n번째 항을 직접 계산하는 수식

 

 

 

  • 는 황금 비율(Golden Ratio)로
  • 1−ϕ는 황금 비율의 보수로, .

 

 

'자료구조 > 알고리즘 기초수학' 카테고리의 다른 글

칸토어 집합  (0) 2024.08.13
행렬식  (0) 2024.08.13
백트래킹 (Backtracking)  (0) 2024.08.12
비트마스크 (Bit Mask)  (0) 2024.08.12
동적 프로그래밍 (Dynamic Programming, DP)  (0) 2024.08.12

백트래킹(Backtracking)


 

조합, 순열, 그래프 탐색, 퍼즐 해결 등에 사용되는 자료구조이다.

"부분해"를 탐색하다가 문제가 발생하면 다시 돌아가서 다른 경로를 시도한다.

이 방식은 깊이 우선 탐색(Depth-First Search)과 비슷하지만, 특정 조건이 만족되지 않을 때 그 경로를 포기하고

이전 상태로 되돌아가서 다른 경로를 탐색하는 차이점이 있다.

 

백트래킹과 깊이 우선 탐색 (DFS)의 차이점
 
특징 백트래킹 깊이 우선 탐색 (DFS)
목표 주어진 문제의 해결책을 찾기 위해 가능한 모든 부분해를 탐색한다 조건을 만족하지 않으면 되돌아가서 다른 선택을 시도 그래프나 트리의 모든 노드를 탐색하여
목표 노드나 조건을 만족하는 노드를 찾는다
사용 목적 조합, 순열, 퍼즐 문제 등에서 가능한 해를 찾기 위해 사용한다 경로 찾기, 사이클 검출, 연결성 확인 등
그래프 탐색에 사용한다
탐색 방식 현재 단계에서 선택을 시도하고 유효하지 않으면
이전 단계로 돌아가서 다른 선택을 시도한다
노드를 깊이 우선으로 탐색하고,모든 자식 노드를 탐색한 후 부모 노드로 돌아온다
경로 검토 각 단계에서 유효성 검사를 통해 유효한 경로만 탐색하며
유효하지 않은 경로는 가지치기하여 탐색하지 않는다
그래프의 모든 경로를 탐색하며, 특정 노드를 찾거나 경로를 탐색한다
구현 방식 재귀 호출로 구현되며
현재 상태에서 가능한 모든 선택을 시도한다
스택을 사용하거나 재귀 호출을 통해 구현되며
모든 자식 노드를 깊이 탐색한 후 돌아온다

부분해

전체 문제가 완성된 해답에 도달하기 위해 반복적으로 작업을 수행하는 중간 결과이다.

백트래킹의 작동방식

  1. 경로 선택: 문제를 해결하기 위해 가능한 선택을 하나씩 시도한다
  2. 유효성 검사: 현재 선택이 문제의 조건을 만족하는지 확인한다
  3. 해 결정을 위한 재귀 호출: 선택이 유효하다면, 그 선택을 기반으로 다음 단계로 진행한다
  4. 백트래킹: 만약 현재 경로가 해결책이 아니라면, 선택을 취소하고 이전 상태로 돌아가서 다른 경로를 탐색한다

장점과 단점

  • 장점: 백트래킹은 해를 찾는 과정에서 불필요한 탐색을 줄일 수 있다
  • 단점: 문제의 크기가 커지면 탐색 공간이 급격히 증가하여 시간 복잡도가 높아질 수 있다.
  • 따라서 효율적으로 탐색을 줄이기 위해 추가적인 최적화나 가지치기 기법이 필요할 수 있다
 
 
 
 

'자료구조 > 알고리즘 기초수학' 카테고리의 다른 글

행렬식  (0) 2024.08.13
피보나치 수열  (0) 2024.08.13
비트마스크 (Bit Mask)  (0) 2024.08.12
동적 프로그래밍 (Dynamic Programming, DP)  (0) 2024.08.12
그래프 탐색  (0) 2024.08.12

+ Recent posts