탐욕 알고리즘(Greedy Algorithm)은 최적화 문제를 해결하기 위한 알고리즘 설계 기법 중 하나이다. 이 방법은 각 단계에서 당장 눈앞에 보이는 최선의 선택을 하는 방식으로, 전체적인 최적해를 구하기 위해 부분적인 최적 선택을 반복한다. "탐욕적"이라는 이름은 매 순간 가장 좋아 보이는 것을 선택한다는 점에서 유래한다. 이 알고리즘은 문제를 해결하는 과정에서 되돌아가거나 미래를 고려하지 않고, 현재 상태에서 가장 유리한 결정을 내린다.
탐욕 알고리즘은 동적 계획법(Dynamic Programming)과 함께 대표적인 알고리즘 패러다임으로 분류된다. 그러나 동적 계획법이 모든 가능한 하위 문제를 검토하여 최적해를 구성하는 방식과 달리, 탐욕 알고리즘은 한 번 선택한 결정을 번복하지 않는다. 이로 인해 알고리즘이 단순하고 실행 속도가 빠르다는 장점이 있다. 하지만 모든 문제에 적용할 수 있는 것은 아니며, 특정 조건을 만족하는 문제에서만 최적해를 보장한다.
탐욕 알고리즘의 핵심은 탐욕 선택 속성(Greedy Choice Property)과 최적 부분 구조(Optimal Substructure)라는 두 가지 조건이다. 탐욕 선택 속성은 각 단계에서의 탐욕적 선택이 전체 최적해를 구성하는 데 포함된다는 것을 의미한다. 최적 부분 구조는 문제의 최적해가 그 부분 문제의 최적해로 구성될 수 있는 구조를 말한다. 이 두 조건을 만족하는 문제에서는 탐욕 알고리즘이 항상 최적의 해답을 찾아낸다.
이 알고리즘은 활동 선택 문제, 허프만 코딩, 최소 신장 트리를 찾는 프림 알고리즘과 크루스칼 알고리즘, 그리고 다익스트라 알고리즘 등 다양한 분야에서 성공적으로 적용된다.
탐욕 알고리즘은 각 단계에서 현재 상황에서 가장 좋아 보이는 선택을 하는 방식으로 문제를 해결하는 알고리즘 설계 기법이다. 이 접근법은 전체 문제의 최적해를 구하기 위해, 매 순간 지역적으로 최적인 선택을 반복적으로 수행한다. 이러한 선택은 한 번 결정되면 다시 되돌리지 않으며, 이후의 선택에 영향을 미친다. 따라서 탐욕 알고리즘은 문제를 해결하는 과정에서 발생하는 결정들의 시퀀스를 구성한다.
탐욕 알고리즘이 올바른 최적해를 도출하기 위해서는 일반적으로 두 가지 핵심 속성을 만족해야 한다. 첫 번째는 탐욕 선택 속성이다. 이는 각 단계에서 탐욕적으로 선택한 지역적 최적해가 전체 문제의 최적해를 구성하는 데 사용될 수 있음을 의미한다. 즉, 탐욕 알고리즘이 매 순간 내리는 선택이 최종 해답의 일부가 될 수 있어야 한다. 두 번째는 최적 부분 구조이다. 이는 문제의 최적해가 그 부분 문제들의 최적해로부터 구성될 수 있는 성질을 말한다. 만약 어떤 문제의 최적해가 부분 문제들의 최적해를 포함한다면, 탐욕 선택 이후 남은 부분 문제는 원래 문제의 축소된 형태가 되며, 이를 독립적으로 해결할 수 있다.
이 두 속성이 모두 성립하는 문제에 대해서만 탐욕 알고리즘은 항상 전역 최적해를 보장한다. 예를 들어, 동전 거스름돈 문제에서 특정 화폐 체계(예: 500원, 100원, 50원, 10원)에서는 탐욕 알고리즘이 최소 동전 개수를 찾지만, 일반적인 화폐 체계에서는 그렇지 않을 수 있다[1]. 따라서 탐욕 알고리즘을 설계할 때는 이러한 속성들을 엄밀하게 증명하는 것이 필수적이다.
탐욕 알고리즘이 항상 최적해를 찾을 수 있으려면 문제가 특정한 성질을 만족해야 한다. 그 핵심 성질 중 하나가 탐욕 선택 속성이다.
탐욕 선택 속성은 각 단계에서 지역적으로 최적인 선택이 전체 문제의 최적해로 이어진다는 성질을 말한다. 즉, 탐욕 알고리즘이 매 순간 가장 좋아 보이는 선택을 하더라도, 그 선택이 최종적인 최적해를 구성하는 데 방해가 되지 않음을 의미한다. 이 속성이 성립하면, 알고리즘은 과거의 선택을 다시 고려하거나 되돌아볼 필요 없이 앞으로만 나아가며 해를 구축할 수 있다.
예를 들어, 활동 선택 문제에서 "가장 일찍 끝나는 활동"을 선택하는 기준은 탐욕 선택 속성을 만족한다. 한 단계에서 가장 일찍 끝나는 활동을 선택하는 것이 이후에 더 많은 활동을 배정할 수 있는 가능성을 최대화하며, 이 선택은 반드시 어떤 최적해에 포함된다는 것이 증명 가능하다[2]. 반대로, 만약 "가장 짧은 활동"이나 "가장 늦게 시작하는 활동"을 선택하는 기준은 탐욕 선택 속성을 일반적으로 만족하지 않아 최적해를 보장하지 못한다.
따라서 탐욕 알고리즘을 설계할 때는 단순히 직관적인 선택 기준을 세우는 것뿐만 아니라, 그 기준이 탐욕 선택 속성을 실제로 만족하는지 엄밀하게 증명하는 것이 필수적이다. 이 속성의 성립 여부는 문제마다 다르며, 증명이 실패한다면 해당 알고리즘은 근사 알고리즘이 되거나 다른 설계 기법(예: 동적 계획법)을 고려해야 한다.
최적 부분 구조는 문제의 최적해가 그 부분 문제들의 최적해로 구성될 수 있는 성질을 말한다. 이는 탐욕 알고리즘이 성공적으로 적용되기 위해 필요한 두 가지 핵심 조건 중 하나이다[3]]이다].
어떤 문제가 최적 부분 구조를 가진다는 것은, 전체 문제에 대한 최적해가 부분 문제에 대한 최적해를 포함하고 있음을 의미한다. 예를 들어, 최단 경로 문제에서 A에서 C까지의 최단 경로가 A-B-C라면, 그 부분 경로인 A-B와 B-C 역시 각 구간의 최단 경로여야 한다. 만약 A-B가 최단 경로가 아니라면, 전체 경로 A-B-C도 최단 경로가 될 수 없다. 이러한 구조 덕분에 탐욕 알고리즘은 각 단계에서 지역 최적해를 선택함으로써, 그 선택이 전체 문제의 최적해를 구성하는 부분이 될 수 있다.
최적 부분 구조는 탐욕 알고리즘뿐만 아니라 동적 계획법에서도 중요한 개념이다. 두 방법론 모두 이 성질에 의존하지만, 접근 방식이 다르다. 동적 계획법은 모든 부분 문제를 고려하고 그 해를 저장하여 상위 문제를 해결하는 반면, 탐욕 알고리즘은 각 단계에서 한 번의 탐욕적 선택을 하고 나머지 부분 문제는 그 선택 이후에 발생하는 단일 부분 문제로 축소한다. 따라서 탐욕 알고리즘이 작동하려면, 탐욕적 선택 이후 남은 문제가 원래 문제와 동일한 구조를 유지하며, 그 부분 문제의 최적해에 처음의 탐욕적 선택을 더하면 원래 문제의 최적해가 되어야 한다.
활동 선택 문제는 한정된 자원(예: 단일 강의실)을 공유하는 여러 활동들의 집합에서, 서로 겹치지 않는 최대 개수의 활동들을 선택하는 문제이다. 각 활동은 시작 시간과 종료 시간을 가지며, 탐욕 알고리즘은 종료 시간이 가장 빠른 활동을 반복적으로 선택하는 방식으로 최적해를 찾는다. 이 방법은 탐욕 선택 속성을 만족하여 항상 최대 크기의 호환 가능한 활동 집합을 제공한다.
허프만 코딩은 데이터 압축에 널리 사용되는 탐욕 알고리즘이다. 문자 빈도가 주어졌을 때, 접두사 코드를 생성하여 전체 인코딩된 메시지의 길이를 최소화한다. 알고리즘은 가장 빈도가 낮은 두 심볼을 반복적으로 병합하여 이진 트리를 아래에서 위로 구성한다. 각 병합 단계에서 가장 작은 빈도를 가진 항목을 선택하는 탐욕적 선택이 전체적으로 최적의 코드를 만들어낸다.
최소 비용으로 모든 정점을 연결하는 최소 신장 트리 문제에는 대표적인 두 탐욕 알고리즘이 있다. 크루스칼 알고리즘은 전체 간선 중 비용이 가장 작으면서 사이클을 형성하지 않는 간선을 하나씩 선택한다. 프림 알고리즘은 임의의 시작 정점에서 출발하여, 현재 트리에 연결될 수 있는 간선 중 최소 비용 간선을 반복적으로 추가한다. 두 알고리즘 모두 간선의 가중치를 기준으로 한 탐욕적 선택을 통해 최적의 신장 트리를 구성한다.
알고리즘 | 핵심 탐욕 선택 기준 | 주요 특징 |
|---|---|---|
종료 시간이 가장 빠른 활동 | 서로 겹치지 않는 최대 활동 집합 선택 | |
빈도가 가장 낮은 두 노드 | 최적 접두사 코드를 통한 무손실 압축 | |
전체 그래프에서 최소 가중치 간선 | 사이클 생성 방지를 위한 유니온 파인드 자료구조 사용 | |
현재 트리에 인접한 최소 가중치 간선 | 한 정점에서 시작하여 트리를 확장 | |
확정되지 않은 정점 중 최단 거리 정점 | 단일 출발점에서 모든 정점까지의 최단 경로 계산 |
다익스트라 최단 경로 알고리즘은 가중치가 음이 아닌 그래프에서 한 출발점으로부터 다른 모든 정점까지의 최단 경로를 찾는다. 알고리즘은 아직 최단 거리가 확정되지 않은 정점들 중, 출발점으로부터의 거리가 가장 짧은 정점을 탐욕적으로 선택하여 그 거리를 확정한다. 이 과정을 반복함으로써 모든 정점에 대한 최단 경로를 효율적으로 계산한다.
활동 선택 문제는 탐욕 알고리즘의 대표적인 예시로, 한정된 자원(예: 하나의 강의실)을 공유해야 하는 여러 활동들의 최대 개수를 선택하는 문제이다. 각 활동은 시작 시간과 종료 시간을 가지며, 한 번에 하나의 활동만 진행할 수 있다. 목표는 서로 시간이 겹치지 않는 활동들의 집합을 선택하여 그 크기를 최대화하는 것이다.
이 문제에 대한 탐욕적 해법은 직관적이다. 가장 먼저 종료하는 활동을 선택하면, 남은 시간을 다른 활동에 할당할 기회가 최대화된다. 따라서 알고리즘은 다음과 같이 진행한다.
1. 모든 활동을 종료 시간 기준으로 오름차순 정렬한다.
2. 첫 번째 활동(가장 먼저 끝나는 활동)을 선택한다.
3. 선택한 활동의 종료 시간 이후에 시작하는 활동 중, 가장 먼저 종료하는 활동을 다음으로 선택한다.
4. 더 이상 선택할 활동이 없을 때까지 3단계를 반복한다.
이 접근법은 탐욕 선택 속성과 최적 부분 구조를 모두 만족한다. 가장 먼저 끝나는 활동을 포함하는 최적해가 반드시 존재함이 증명되며, 한 활동을 선택한 후 남은 부분 문제는 원래 문제와 동일한 구조를 가진다. 따라서 각 단계의 지역적 최선의 선택이 전체적인 최적해로 이어진다.
단계 | 선택된 활동 | 종료 시간 | 다음으로 고려할 활동 (시작 시간 ≥ 이전 종료 시간) |
|---|---|---|---|
1 | A1 | 4 | A3 (시작 3) |
2 | A3 | 7 | A6 (시작 6) |
3 | A6 | 10 | A8 (시작 8) |
4 | A8 | 11 | 없음 |
위 표는 활동 집합이 주어졌을 때 알고리즘의 실행 예시를 보여준다. 이 알고리즘의 시간 복잡도는 주로 정렬에 의해 결정되며, O(n log n)이다. 활동 선택 문제는 작업 스케줄링이나 회의실 배정 등 실생활에서 널리 응용된다.
허프만 코딩은 데이터 압축 분야에서 널리 사용되는 무손실 압축 알고리즘이다. 이 알고리즘은 1952년 데이비드 허프만이 개발하였으며, 각 문자의 빈도수에 따라 가변 길이의 코드를 할당하여 전체 데이터의 평균 코드 길이를 최소화한다. 기본 원리는 빈도가 높은 문자에는 짧은 이진 코드를, 빈도가 낮은 문자에는 긴 이진 코드를 부여하는 것이다.
알고리즘은 허프만 트리라는 이진 트리를 구성하는 과정을 통해 수행된다. 먼저, 압축할 데이터에서 각 문자의 출현 빈도를 계산한다. 그 후, 모든 문자를 리프 노드로 가지는 최소 힙을 생성한다. 힙에서 빈도가 가장 낮은 두 노드를 반복적으로 꺼내, 이들을 자식으로 하는 새로운 부모 노드를 만들어 힙에 다시 삽입한다. 이 부모 노드의 빈도는 두 자식 노드 빈도의 합이다. 이 과정을 단 하나의 루트 노드가 남을 때까지 반복하면 허프만 트리가 완성된다. 트리에서 루트부터 각 리프(문자)까지 이동할 때, 왼쪽 간선은 0, 오른쪽 간선은 1로 부호화하여 각 문자의 최종 코드를 얻는다.
허프만 코딩은 탐욕 알고리즘의 전형적인 예로, 각 단계에서 가장 빈도가 낮은 두 노드를 합치는 지역적 최적 선택이 전체적으로 최적의 접두사 코드를 만들어낸다. 이 알고리즘이 생성하는 코드는 접두사 속성을 만족하여, 어떤 코드도 다른 코드의 접두사가 되지 않아 복호화 시 모호함이 없다.
특징 | 설명 |
|---|---|
압축 방식 | |
핵심 아이디어 | 빈도에 따른 가변 길이 접두사 코드 할당 |
자료 구조 | |
시간 복잡도 | O(n log n) (n: 고유 문자 수) |
주요 응용 |
이 방법은 고정 길이 코딩보다 효율적이지만, 압축하려는 데이터의 문자 빈도 분포를 미리 알아야 한다는 제약이 있다. 실제 구현에서는 허프만 트리 구조 자체나 문자 빈도표를 압축 데이터와 함께 저장하여 복호화가 가능하게 한다.
최소 신장 트리는 주어진 가중치가 있는 연결 그래프의 모든 정점을 포함하면서, 간선의 가중치 합이 최소가 되는 부분 그래프이다. 이 트리는 사이클을 포함하지 않으므로 반드시 트리의 형태를 띤다. 최소 신장 트리를 구하는 대표적인 탐욕 알고리즘으로는 프림 알고리즘과 크루스칼 알고리즘이 있다.
프림 알고리즘은 하나의 정점에서 시작하여 트리를 점차 확장해 나가는 방식이다. 먼저 임의의 시작 정점을 트리에 포함시킨다. 이후 현재까지 구성된 트리에 연결된 간선 중, 아직 트리에 포함되지 않은 정점으로 향하며 가중치가 가장 작은 간선을 탐욕적으로 선택하여 해당 정점과 간선을 트리에 추가한다. 이 과정을 모든 정점이 트리에 포함될 때까지 반복한다. 이 알고리즘의 핵심은 각 단계에서 현재 트리와 외부 정점을 연결하는 최소 가중치 간선(절단을 가로지르는 최소 간선)을 선택하는 것이다.
크루스칼 알고리즘은 모든 간선을 가중치 기준으로 오름차순 정렬한 후, 가중치가 가장 작은 간선부터 순서대로 검토하며 트리를 구성한다. 현재 검토 중인 간선이 사이클을 형성하지 않으면 해당 간선을 최소 신장 트리에 포함시킨다. 사이클 형성 여부는 유니온 파인드 자료 구조를 사용하여 효율적으로 판단할 수 있다. 이 과정은 (정점 수 - 1)개의 간선이 선택될 때까지, 혹은 모든 간선을 검토할 때까지 계속된다.
두 알고리즘의 성능과 특징은 다음과 같이 비교할 수 있다.
알고리즘 | 시간 복잡도 (인접 리스트) | 기본 동작 방식 | 사용 자료 구조 |
|---|---|---|---|
프림 알고리즘 | O(E log V) | 정점 중심 확장 | 우선순위 큐 (최소 힙) |
크루스칼 알고리즘 | O(E log E) | 간선 중심 선택 | 유니온 파인드 (상호 배타적 집합) |
두 알고리즘 모두 탐욕적 선택의 안전성, 즉 각 단계에서 선택한 간선이 최종 최소 신장 트리에 반드시 포함된다는 것이 수학적으로 증명되어 있다. 이들은 네트워크 설계, 통신망 구축, 도로망 계획 등 다양한 최적화 문제에 폭넓게 응용된다.
다익스트라 최단 경로 알고리즘은 가중 그래프에서 한 정점(소스)에서 다른 모든 정점까지의 최단 경로를 찾는 탐욕 알고리즘이다. 이 알고리즘은 에츠허르 다익스트라가 1956년에 고안했으며, 음의 가중치를 갖지 않는 그래프에서만 정확하게 동작한다[4].
알고리즘은 다음과 같은 단계로 진행된다. 먼저, 시작 정점의 거리를 0으로, 다른 모든 정점의 거리를 무한대로 초기화한다. 아직 방문하지 않은 정점들 중 현재 알고 있는 거리가 가장 짧은 정점을 탐욕적 선택으로 골라 방문(확정)한다. 그런 다음, 이 방문한 정점을 통해 인접한 정점들로 가는 경로의 거리를 계산하고, 기존에 알려진 거리보다 짧으면 거리 정보를 갱신한다. 이 과정을 모든 정점을 방문할 때까지 반복한다. 이때 가장 짧은 거리의 정점을 선택하는 과정은 일반적으로 우선순위 큐(예: 최소 힙)를 사용해 효율적으로 구현한다.
다익스트라 알고리즘의 핵심은 매 단계에서 '아직 확정되지 않은 정점 중 가장 가까운 정점'을 선택한다는 탐욕적 선택 속성에 있다. 이 선택은 이후의 선택을 번복하지 않으며, 음의 가중치가 없다는 가정 하에 이 선택이 항상 최적의 경로를 구성함이 증명된다. 알고리즘의 시간 복잡도는 구현 방식에 따라 다르며, 인접 리스트와 이진 힙을 사용한 우선순위 큐를 결합하면 O(|E| + |V| log |V|)의 효율적인 성능을 낸다[5].
알고리즘 구성 요소 | 설명 |
|---|---|
탐욕적 선택 기준 | 방문하지 않은 정점 중 시작점으로부터 현재 알고 있는 거리가 최소인 정점 선택 |
적용 가능 그래프 | 방향/무방향 그래프, 간선의 가중치는 음수가 아니어야 함 |
주요 자료구조 | 거리 배열(distance array), 우선순위 큐(priority queue), 방문 여부 체크 |
시간 복잡도 | 기본 구현: O(\ |
이 알고리즘은 네트워크 라우팅 프로토콜, 교통 네트워크 분석, 로봇 경로 계획 등 실제 응용 분야에서 매우 널리 사용된다.
탐욕 알고리즘을 설계하는 핵심은 각 단계에서 최적해로 가는 '탐욕적 선택'을 어떻게 정의하고, 그 선택이 전체 문제의 최적해를 구성하는 '안전한' 선택임을 증명하는 데 있다. 설계 과정은 일반적으로 두 가지 주요 단계로 나뉜다.
첫 번째 단계는 문제의 탐욕적 선택 기준을 명확히 정의하는 것이다. 이는 각 단계에서 가장 좋아 보이는, 즉 가장 탐욕스러운 선택을 하는 규칙을 수립하는 것을 의미한다. 예를 들어, 활동 선택 문제에서는 '가장 먼저 끝나는 활동'을 선택하고, 허프만 코딩에서는 '가장 빈도가 낮은 두 노드'를 병합하는 것이 선택 기준이다. 이 기준은 문제의 목적에 맞게 설계되며, 설계자의 직관과 경험에 크게 의존한다.
두 번째 단계는 설계한 선택 기준의 '안전성'을 증명하는 것이다. 안전성 증명은 해당 탐욕적 선택이 최종 해답의 일부가 될 수 있음을, 즉 이 선택을 포함하는 최적해가 반드시 존재함을 보이는 과정이다. 이 증명은 주로 '교체' 논증을 통해 이루어진다. 만약 탐욕 알고리즘이 선택한 활동 A가 어떤 최적해 O에 포함되지 않았다고 가정하면, O에 포함된 다른 활동 B를 A로 교체해도 해답의 질이 나빠지지 않음을 보임으로써, 탐욕적 선택이 항상 안전함을 입증한다.
안전성 증명이 성공하면, 설계된 알고리즘은 탐욕 선택 속성을 만족한다고 말할 수 있다. 이는 설계의 가장 중요한 부분으로, 증명 없이는 해당 알고리즘이 단순히 휴리스틱에 불과할 수 있다. 탐욕 알고리즘 설계의 성공 여부는 결국 이 안전한 선택이 문제의 최적 부분 구조와 어떻게 결합되어 전체 최적해를 효율적으로 구성해내는지에 달려 있다.
탐욕 알고리즘을 설계할 때 가장 핵심적인 단계는 각 단계에서 어떤 선택을 할지 결정하는 탐욕적 선택 기준을 명확히 정의하는 것이다. 이 기준은 주어진 문제 상황에서 "현재 가장 좋아 보이는" 선택을 수학적 또는 논리적으로 표현한 규칙이다. 예를 들어, 동전 거스름돈 문제에서는 가장 큰 단위의 동전부터 선택하는 것이 기준이 될 수 있으며, 활동 선택 문제에서는 가장 일찍 끝나는 활동을 선택하는 것이 기준이 된다.
선택 기준을 정의하는 일반적인 접근법은 문제의 목적 함수를 최적화하는 관점에서 출발한다. 목표가 비용 최소화라면 각 단계에서 가장 비용이 적게 드는 선택을, 이익 최대화라면 가장 이익이 큰 선택을 기준으로 삼는다. 그러나 단순히 당장의 비용이나 이익만을 고려하는 것이 항상 전체 최적해로 이어지지는 않는다는 점이 탐욕 알고리즘 설계의 난점이다. 따라서 선택 기준을 수립할 때는 해당 기준이 문제의 탐욕 선택 속성을 만족하는지, 즉 현재의 최선의 선택이 미래의 선택 가능성을 해치지 않으면서 전체 최적해의 일부가 될 수 있는지에 대한 고민이 필요하다.
효과적인 선택 기준은 종종 문제의 데이터를 특정 순서로 정렬하는 것에서 시작된다. 많은 탐욕 알고리즘은 입력 데이터를 정렬한 후, 정렬된 순서대로 "첫 번째" 또는 "마지막" 항목을 선택하는 방식을 취한다. 아래는 몇 가지 대표적인 문제와 그에 따른 탐욕적 선택 기준의 예시이다.
문제 | 탐욕적 선택 기준 | 정렬 기준 (해당되는 경우) |
|---|---|---|
현재 시간과 겹치지 않으면서 가장 일찍 끝나는 활동 선택 | 활동의 종료 시간 기준 오름차순 | |
가장 빈도가 낮은 두 노드를 반복적으로 결합 | 문자 빈도 기준 (우선순위 큐 사용) | |
동전 거스름돈 문제 (표준 동전 체계) | 가장 큰 단위의 동전부터 최대한 사용 | 동전 단위 기준 내림차순 |
단위 무게당 가치가 가장 높은 물품부터 최대한 채움 | 단위 무게당 가치 기준 내림차순 |
이러한 기준을 정의한 후에는, 해당 선택이 안전하다는 것, 즉 최종 해답의 일부가 될 수 있음을 증명하는 안전성 증명 단계가 필수적으로 뒤따른다. 올바른 탐욕적 선택 기준은 문제의 본질을 꿰뚫고, 지역 최적해가 전역 최적해를 구성할 수 있도록 보장한다.
탐욕 알고리즘의 안전성 증명은 해당 알고리즘이 각 단계에서 지역적으로 최적인 선택을 함으로써 전체적인 최적해를 구성할 수 있음을 수학적으로 입증하는 과정이다. 이 증명은 알고리즘이 최적 부분 구조와 탐욕 선택 속성을 만족하는 문제에 대해 올바르게 작동함을 보장하는 핵심 절차이다.
안전성 증명은 일반적으로 두 가지 주요 전략을 통해 이루어진다. 첫 번째는 탐욕 선택 속성을 증명하는 것으로, 탐욕 알고리즘이 첫 번째 선택으로 이루어낸 해가 어떤 최적해에도 포함될 수 있음을 보인다. 두 번째는 최적 부분 구조를 증명하는 것으로, 첫 번째 선택 이후 남은 부분 문제가 원래 문제와 동일한 구조를 유지하며, 그 부분 문제의 최적해에 탐욕 선택을 결합하면 전체 최적해가 됨을 보인다. 대표적인 증명 기법으로는 교환 논법이 있다. 이 방법은 가정된 최적해가 탐욕 알고리즘의 첫 선택을 포함하지 않을 때, 그 선택으로 최적해의 일부 요소를 '교환'하여 새로운 해를 만들고, 이 새로운 해가 최적임을 보여 모순을 이끌어낸다.
안전성 증명의 구체적인 예는 활동 선택 문제에서 확인할 수 있다. 활동 선택 문제에서 탐욕 알고리즘은 가장 일찍 끝나는 활동을 선택한다. 이 선택의 안전성을 증명하기 위해, 알고리즘이 선택한 활동 a1을 포함하지 않는 최적해 A가 있다고 가정한다. 이 최적해 A의 첫 번째 활동을 a1으로 교환해도 새로운 해는 여전히 가능하며(왜냐하면 a1은 A의 첫 활동보다 더 일찍 끝나기 때문), 활동 수는 동일하게 유지된다. 따라서 a1을 포함하는 해도 최적해가 될 수 있음을 보여주며, 이는 탐욕 선택이 안전함을 의미한다. 이와 유사한 논증이 허프만 코딩이나 최소 신장 트리 알고리즘의 정당성 증명에도 적용된다.
결론적으로, 안전성 증명은 탐욕 알고리즘이 단순히 직관에 의존하는 휴리스틱이 아니라, 엄밀한 수학적 근거 위에 설계된 정확한 알고리즘임을 입증한다. 이 증명이 성공하지 못하는 문제에 대해서는 탐욕 알고리즘을 적용할 수 없으며, 동적 계획법이나 다른 패러다임을 고려해야 한다.
탐욕 알고리즘의 가장 큰 장점은 단순하고 직관적이며, 일반적으로 매우 빠른 실행 속도를 보인다는 점이다. 각 단계에서 지역적으로 최선의 선택을 하기 때문에, 복잡한 전역 최적화를 고려하는 다른 알고리즘에 비해 설계와 구현이 비교적 쉽다. 또한, 대부분의 경우 시간 복잡도가 낮아 실용적인 문제에 효율적으로 적용할 수 있다. 예를 들어, 다익스트라 최단 경로 알고리즘이나 프림 알고리즘은 탐욕적 접근을 통해 효율적으로 최적해를 찾아낸다.
그러나 탐욕 알고리즘의 근본적인 단점은 항상 전역 최적해를 보장하지 않는다는 것이다. 각 단계의 지역 최적 선택이 전체 문제의 최적해로 이어지지 않는 경우가 많기 때문이다. 대표적으로 배낭 문제의 '0-1 배낭 문제'는 탐욕 알고리즘으로 최적해를 구할 수 없는 경우에 해당한다. 이는 탐욕 알고리즘이 과거의 선택을 다시 고려하지 않고 미래의 결과를 전망하지 않기 때문에 발생하는 한계이다.
장점 | 단점 |
|---|---|
알고리즘이 단순하고 직관적이다. | 항상 최적해를 보장하지는 않는다. |
일반적으로 실행 시간이 빠르고 효율적이다. | 과거의 선택을 번복하지 않아 부분 최적해에 갇힐 수 있다. |
설계와 구현이 상대적으로 쉽다. | 적용 가능 여부를 수학적으로 증명해야 하는 부담이 있다. |
따라서 탐욕 알고리즘을 사용하기 전에는 해당 문제가 탐욕 선택 속성과 최적 부분 구조를 모두 만족하는지 신중하게 검토해야 한다. 이러한 속성들이 성립함이 증명된 문제에 대해서만 탐욕 알고리즘은 최적해를 제공하는 강력한 도구가 된다.
탐욕 알고리즘의 가장 큰 장점은 설계와 구현이 직관적이고 단순하다는 점이다. 알고리즘의 핵심은 각 단계에서 가장 좋아 보이는 선택을 하는 것이므로, 복잡한 전역 최적화를 고려하지 않고도 비교적 쉽게 알고리즘을 구성할 수 있다. 이 단순성은 코드의 가독성과 유지보수성을 높인다.
또한, 이러한 단순한 접근 방식은 대체로 높은 계산 효율성을 가져온다. 대부분의 탐욕 알고리즘은 시간 복잡도가 낮아, 입력 크기가 커도 빠르게 실행된다. 예를 들어, 활동 선택 문제나 최소 신장 트리를 구하는 크루스칼 알고리즘은 효율적인 정렬 이후 선형 시간에 가까운 성능을 보인다. 이는 같은 문제를 완전 탐색이나 동적 계획법으로 풀 경우 발생할 수 있는 지수 시간 또는 높은 다항식 시간의 복잡도를 피할 수 있게 해준다.
알고리즘 예시 | 일반적인 시간 복잡도 | 비고 |
|---|---|---|
O(n log n) | 주로 정렬 시간이 지배적 | |
O(E log V) | 유니온-파인드 자료구조 사용 시 | |
O(E log V) | 우선순위 큐 사용 시 | |
O(n log n) | 최소 힙 사용 시 |
결과적으로, 탐욕 알고리즘은 최적해를 보장하는 문제 영역에서 매우 강력한 도구가 된다. 단순한 논리와 빠른 실행 속도 덕분에 실시간 시스템이나 제한된 계산 자원을 가진 환경에서 널리 활용된다.
탐욕 알고리즘의 가장 큰 단점은 모든 문제에 대해 최적해를 보장하지 않는다는 점이다. 이는 알고리즘이 각 단계에서 지역적으로 최선의 선택을 하기 때문에, 전체적인 관점에서는 최종 결과가 최적이 아닐 수 있음을 의미한다. 예를 들어, 배낭 문제 중 물건을 쪼갤 수 없는 0-1 배낭 문제에서, 탐욕 알고리즘은 단위 무게당 가치가 가장 높은 물건부터 선택하는 방식을 사용할 수 있다. 그러나 이 방식은 항상 최대 가치를 만들어내지 못하며, 경우에 따라서는 매우 나쁜 해를 제공할 수 있다[6].
이러한 실패의 근본 원인은 문제가 탐욕 선택 속성이나 최적 부분 구조를 갖추지 않았기 때문이다. 탐욕 알고리즘이 성공하려면, 각 단계의 탐욕적 선택이 이후의 선택을 방해하지 않으면서 전체 최적해의 일부가 되어야 한다. 많은 최적화 문제, 특히 NP-난해 문제들은 이 속성을 만족하지 않아 탐욕 접근법으로는 최적해에 근접하기 어렵다. 대신, 근사 알고리즘으로 활용되거나, 동적 계획법과 같은 보다 포괄적인 방법이 필요하다.
문제 예시 | 탐욕 알고리즘 접근 | 최적해 보장 여부 | 비고 |
|---|---|---|---|
동전 거스름돈 문제 (일반 화폐 체계) | 가장 큰 단위 동전부터 선택 | 보장됨 | 미국이나 한국의 화폐 단위처럼 특수한 경우에만 성립 |
동전 거스름돈 문제 (임의의 화폐 체계) | 가장 큰 단위 동전부터 선택 | 보장되지 않음 | 예: 동전 단위가 {1, 3, 4}원일 때 6원을 만들 경우 |
가장 가까운 도시부터 방문 (최근접 이웃) | 보장되지 않음 | 휴리스틱 알고리즘으로 사용됨 |
따라서 탐욕 알고리즘을 설계하거나 적용할 때는, 해당 문제가 탐욕 알고리즘의 적용 조건을 만족하는지 엄밀하게 분석하고 증명하는 과정이 필수적이다. 단순하고 빠른 해결책을 제공할 수 있지만, 그 해가 최적인지에 대한 검증 없이는 신뢰할 수 없는 결과를 초래할 수 있다.
탐욕 알고리즘은 각 단계에서 가장 좋아 보이는 선택을 하는 방식으로, 항상 최적해를 찾아내지는 못한다. 이 알고리즘이 실패하는 대표적인 경우는 배낭 문제의 변형 중 하나인 '0-1 배낭 문제'이다. 이 문제에서는 각 물건을 통째로 넣거나 넣지 않아야 하며, 단위 무게당 가치가 가장 높은 물건부터 선택하는 탐욕적 접근법은 최적해를 보장하지 않는다[7]. 또한, 모든 쌍의 최단 경로를 찾는 문제나 외판원 문제와 같이 복잡한 제약 조건이 있는 문제에서도 탐욕 알고리즘은 부적합하다.
이러한 한계를 극복하는 주요 대안은 동적 계획법이다. 두 방법의 핵심적인 차이는 다음과 같다.
특성 | 탐욕 알고리즘 | 동적 계획법 |
|---|---|---|
접근 방식 | 각 단계의 지역 최적 선택 | 모든 가능한 하위 문제를 고려하여 중복 계산을 피함 |
최적성 보장 | 최적 부분 구조가 성립하면 일반적으로 보장 | |
시간 복잡도 | 일반적으로 낮음 (O(n log n) 등) | 일반적으로 높음 (다항 시간 또는 지수 시간) |
공간 복잡도 | 일반적으로 낮음 | 중간 결과 저장을 위해 일반적으로 높음 |
적합한 문제 | 0-1 배낭 문제, 최단 경로(플로이드-워셜), 편집 거리 |
따라서, 문제를 해결할 때는 먼저 그 문제가 탐욕 알고리즘의 두 가지 필수 속성을 만족하는지 검증해야 한다. 만족하지 않는다면, 동적 계획법이나 분기 한정법, 백트래킹과 같은 보다 포괄적인 알고리즘 설계 기법을 고려해야 한다.
탐욕 알고리즘이 항상 최적해를 찾아내지 못하는 경우는 여러 가지가 존재한다. 대표적인 예로 배낭 문제가 있다. 무게 제한이 있는 배낭에 가치와 무게가 다른 물건들을 최대한 가치 있게 채우는 문제에서, 탐욕 알고리즘은 단위 무게당 가치가 가장 높은 물건부터 선택하는 방식을 취할 수 있다. 그러나 이 방법은 물건을 쪼갤 수 없는 0-1 배낭 문제에서는 최적해를 보장하지 않는다. 예를 들어, 배낭의 용량이 50이고 물건 A(가치 60, 무게 10), B(가치 100, 무게 20), C(가치 120, 무게 30)가 있을 때, 단위 무게당 가치는 A(6), B(5), C(4)이다. 탐욕 알고리즘은 A, B를 선택해 총 가치 160을 얻지만, 최적해는 B와 C를 선택해 총 가치 220을 얻는 경우이다.
또 다른 실패 사례는 외판원 문제이다. 이 문제는 여러 도시를 한 번씩만 방문하고 출발점으로 돌아오는 최단 경로를 찾는 것이다. 탐욕 알고리즘은 현재 위치에서 가장 가까운, 아직 방문하지 않은 도시를 반복적으로 선택하는 최근접 이웃 알고리즘을 적용할 수 있다. 하지만 이 방법은 초기 선택이 전체 경로를 열악하게 만들어 장기적으로 훨씬 비효율적인 경로를 생성할 수 있다. 이는 탐욕 알고리즘이 지역적 최적 선택이 전역적 최적 선택으로 이어지지 않는 대표적인 경우이다.
문제 | 탐욕 기준 | 실패 원인 |
|---|---|---|
0-1 배낭 문제 | 단위 무게당 최고 가치 선택 | 선택한 물건이 배낭 용량을 낭비해 전체 가치를 떨어뜨림 |
외판원 문제 | 현재 위치에서 최근접 도시 선택 | 초기 선택이 후반 경로를 크게 비효율적으로 만듦 |
동전 교환 문제 (특정 화폐 체계) | 가장 큰 액면가 동전 선택 | 특정 액면가 조합에서 최소 동전 수를 보장하지 않음[8] |
이러한 실패는 문제가 탐욕 선택 속성이나 최적 부분 구조를 갖추지 않았기 때문에 발생한다. 탐욕 알고리즘을 적용하기 전에는 해당 문제가 이 두 가지 속성을 만족하는지 신중하게 검토해야 한다. 만족하지 않는다면 동적 계획법이나 백트래킹과 같은 다른 알고리즘 설계 기법이 더 적합한 접근법이 될 수 있다.
동적 계획법과 탐욕 알고리즘은 모두 복잡한 문제를 더 작은 하위 문제로 분해하여 해결하는 최적화 기법이다. 그러나 문제에 접근하는 방식과 적용 가능한 조건, 그리고 보장하는 해의 성질에서 근본적인 차이를 보인다.
핵심적인 차이는 문제를 구성하는 하위 문제들 사이의 관계와 해를 구하는 순서에 있다. 동적 계획법은 각 하위 문제의 해가 다른 하위 문제의 해에 의존적이며, 이러한 중복된 하위 문제들을 메모이제이션이나 타뷸레이션을 통해 한 번만 계산하여 전체 최적해를 구성한다. 반면, 탐욕 알고리즘은 각 단계에서 지역적으로 최적이라고 판단되는 선택을 하며, 한 번 선택한 결정은 이후에 번복하지 않는다. 이는 하위 문제들 사이의 독립성을 가정한다.
다음 표는 두 기법의 주요 특성을 비교한다.
특성 | 탐욕 알고리즘 | 동적 계획법 |
|---|---|---|
접근 방식 | 각 단계의 지역적 최적 선택 | 모든 가능한 하위 문제를 고려한 후 전역적 최적해 도출 |
하위 문제 | 일반적으로 독립적 | 중복되고 상호 의존적 |
계산 복잡도 | 일반적으로 더 낮음 (예: O(n log n)) | 일반적으로 더 높음 (예: O(n²) 또는 O(n³)) |
최적해 보장 | 최적 부분 구조가 성립하면 항상 보장 | |
대표 예시 | 플로이드-워셜 알고리즘, 배낭 문제 (0-1) |
적용 가능성을 결정하는 것은 문제가 가진 구조이다. 탐욕 알고리즘이 성공하려면 탐욕 선택 속성, 즉 각 단계의 지역 최적 선택이 전역 최적해로 이어진다는 성질이 반드시 증명되어야 한다. 동적 계획법은 이 속성이 필요 없으며, 단지 최적 부분 구조(전체 문제의 최적해가 하위 문제의 최적해로 구성됨)만 충족하면 된다. 따라서 배낭 문제에서 탐욕 알고리즘은 분수 배낭 문제에는 최적해를 제공하지만, 0-1 배낭 문제에는 최적해를 보장하지 않으며, 후자는 일반적으로 동적 계획법으로 해결한다.
탐욕 알고리즘은 각 단계에서 지역적으로 최적이라고 판단되는 선택을 반복함으로써 전역적인 해답에 도달하려는 접근법이다. 이 원리는 직관적이고 구현이 비교적 간단하여 여러 실용적인 분야에서 널리 응용된다. 특히 최적화 문제나 효율적인 자원 할당이 필요한 상황에서 빈번히 사용된다.
자료 압축 분야에서는 허프만 코딩이 대표적인 예이다. 이 알고리즘은 문자의 빈도수를 분석하여 빈도가 높은 문자에는 짧은 이진 코드를, 낮은 문자에는 긴 코드를 할당한다. 각 단계에서 가장 빈도가 낮은 두 노드를 합치는 탐욕적 선택을 반복하여 최적 접두사 코드를 생성한다. 이는 무손실 압축의 기초가 되며, ZIP이나 JPEG 같은 표준 포맷에도 그 원리가 적용된다.
네트워크 라우팅과 통신에서는 효율적인 데이터 경로 설정에 탐욕 알고리즘이 활용된다. 다익스트라 알고리즘은 네트워크 노드 간의 최단 경로를 찾는 데 사용되며, 각 단계에서 아직 방문하지 않은 노드 중 출발지로부터 거리가 가장 짧은 노드를 선택한다. 이 방법은 인터넷 프로토콜의 라우팅 알고리즘과 같은 네트워크 인프라 설계의 핵심이 된다. 또한, 최소 신장 트리를 구하는 프림 알고리즘이나 크루스칼 알고리즘은 통신 네트워크, 도로망, 전력망 등의 연결 비용을 최소화하는 설계에 응용된다.
작업 스케줄링 및 자원 할당 문제에서도 탐욕 접근법은 효과적이다. 활동 선택 문제의 해법은 한정된 자원(예: 강의실 하나)을 사용하려는 여러 활동(예: 수업)이 있을 때, 최대한 많은 활동을 스케줄링하는 방법을 제공한다. 이는 운영체제의 CPU 스케줄링, 공장의 생산 라인 계획, 또는 클라우드 컴퓨팅의 가상 자원 할당과 같은 문제에 적용될 수 있다. 각 단계에서 가장 빨리 끝나는 활동을 선택하는 간단한 규칙이 최적의 해를 보장하는 대표적인 사례이다.
응용 분야 | 대표 알고리즘/문제 | 주요 활용 예 |
|---|---|---|
자료 압축 | 텍스트, 이미지 무손실 압축 (ZIP, PNG) | |
네트워크 라우팅 | 다익스트라 알고리즘, 최소 신장 트리 알고리즘 | 인터넷 라우팅, 통신망 구축 |
작업 스케줄링 | CPU 스케줄링, 자원 할당, 회의실 배정 |
탐욕 알고리즘은 자료 압축 분야에서 효율적인 압축 알고리즘을 설계하는 데 핵심적인 역할을 한다. 특히 무손실 압축에서, 데이터의 통계적 속성을 기반으로 각 기호에 가변 길이의 코드를 할당하는 엔트로피 부호화 기법에 널리 적용된다. 이는 자주 나타나는 기호에는 짧은 코드를, 드물게 나타나는 기호에는 긴 코드를 부여하여 전체 데이터의 평균 코드 길이를 최소화하는 것이 목표이다.
가장 대표적인 예는 데이비드 허프만이 1952년에 제안한 허프만 코딩이다. 이 알고리즘은 주어진 기호들의 빈도수에 기반하여 이진 트리를 탐욕적으로 구성한다. 매 단계에서 가장 빈도가 낮은 두 개의 기호(또는 서브트리)를 선택하여 합치는 과정을 반복한다[9]. 이렇게 생성된 허프만 트리의 잎 노드에서 루트 노드까지의 경로가 각 기호의 코드가 되며, 이 코드는 접두사 코드의 속성을 만족하여 다른 코드의 접두사가 되지 않아 복호화 시 모호함이 없다.
허프만 코딩 외에도, 런 렝스 부호화와 같은 간단한 압축 기법도 탐욕적 접근의 일종으로 볼 수 있다. 이 기법은 연속적으로 반복되는 동일한 기호(런)를 (기호, 반복 횟수) 쌍으로 치환하는데, 입력 데이터 스트림을 순차적으로 읽으며 현재 기호의 연속 구간을 즉시 식별하고 인코딩한다는 점에서 탐욕적이다.
알고리즘 | 핵심 탐욕적 선택 | 압축 분류 | 주요 특징 |
|---|---|---|---|
가장 낮은 빈도의 두 노드 병합 | 무손실 압축/엔트로피 부호화 | 최적 접두사 코드 생성 | |
현재 입력 기호의 연속 구간 인식 | 무손실 압축 | 단순하고 특정 데이터(이미지, 텍스트)에 효율적 |
이러한 탐욕 알고리즘 기반의 압축 기술은 ZIP, GZIP, JPEG (엔트로피 코딩 단계), MP3 등 수많은 현대적인 압축 표준과 파일 형식의 기반을 이룬다. 이들은 계산 복잡도가 비교적 낮으면서도 우수한 압축률을 제공하여 실시간 처리나 대용량 데이터 저장에 매우 실용적이다.
네트워크 라우팅은 데이터 패킷이 출발지에서 목적지까지 효율적으로 전달되도록 경로를 결정하는 과정이다. 탐욕 알고리즘은 각 라우터가 현재 자신이 가진 정보를 바탕으로, 최적의 다음 홉(hop)을 즉각적으로 선택하는 방식으로 널리 적용된다. 이는 전체 네트워크 경로를 한 번에 계산하는 것이 아니라, 매 단계에서 가장 좋아 보이는 지역적 결정을 내리는 탐욕적 선택의 전형적인 사례이다.
가장 대표적인 예는 다익스트라 알고리즘을 이용한 최단 경로 라우팅이다. 각 라우터는 네트워크를 하나의 가중 그래프로 모델링하고, 자신을 출발점으로 하여 다른 모든 노드까지의 최단 경로를 계산한다. 알고리즘은 매 단계에서 아직 방문하지 않은 노드 중 출발점으로부터 거리가 가장 짧은 노드를 탐욕적으로 선택하여 확정한다. 이 방식은 OSPF(Open Shortest Path First)와 같은 링크 상태 라우팅 프로토콜의 핵심을 이룬다.
프로토콜/기법 | 사용하는 탐욕 알고리즘 | 주요 특징 |
|---|---|---|
OSPF, IS-IS | 링크 상태 정보를 기반으로 전체 네트워크 토폴로지에서 최단 경로 계산 | |
RIP (라우팅 정보 프로토콜) | 거리 벡터 라우팅 (Bellman-Ford 알고리즘의 분산적 구현) | 이웃 라우터로부터 받은 정보를 바탕으로 목적지까지의 홉 수를 최소화하는 방향 선택 |
이러한 탐욕적 접근법의 장점은 계산이 비교적 간단하고 빠르며, 분산 환경에서 실시간으로 경로를 결정할 수 있다는 점이다. 그러나 네트워크 상태가 동적으로 변할 때, 지역적 최적 선택이 전체 네트워크의 혼잡이나 불균형을 초래할 수 있는 한계도 존재한다. 이를 보완하기 위해 트래픽 엔지니어링이나 QoS(서비스 품질) 라우팅에서는 더 포괄적인 제약 조건을 고려하는 다른 최적화 기법이 함께 사용되기도 한다.
작업 스케줄링 문제는 탐욕 알고리즘이 효과적으로 적용되는 대표적인 분야이다. 이 문제는 한정된 자원(예: 단일 프로세서, 기계)에서 여러 작업을 처리할 때, 특정 기준(예: 총 완료 시간 최소화, 지연 작업 수 최소화)에 따라 최적의 순서를 찾는 것을 목표로 한다. 가장 일반적인 형태는 각 작업이 처리 시간과 마감 기한을 가지고 있을 때, 작업들의 순서를 결정하는 것이다.
작업 스케줄링에 사용되는 대표적인 탐욕 전략은 '가장 짧은 처리 시간 우선'과 '가장 빠른 마감 기한 우선'이다. '가장 짧은 처리 시간 우선' 방법은 처리 시간이 가장 짧은 작업부터 순서대로 배정한다. 이 방법은 모든 작업의 총 완료 시간(또는 평균 대기 시간)을 최소화하는 최적해를 보장한다. 반면, '가장 빠른 마감 기한 우선' 방법은 마감 기한이 가장 임박한 작업을 우선적으로 처리한다. 이 방법은 지연되는 작업의 수를 최소화하거나, 모든 작업이 마감 기한 내에 완료될 수 있는지 판단하는 데 유용하다.
다음 표는 네 개의 작업을 '가장 짧은 처리 시간 우선' 규칙으로 스케줄링한 예시를 보여준다.
작업 | 처리 시간 | 완료 시간 |
|---|---|---|
A | 3 | 3 |
B | 1 | 4 (3+1) |
C | 6 | 10 (4+6) |
D | 2 | 12 (10+2) |
위 예시에서 총 완료 시간의 합은 3+4+10+12 = 29이다. 만약 작업을 다른 순서(예: D, C, B, A)로 배정하면 총 완료 시간의 합은 더 커지게 되어, 탐욕적 선택이 최적해로 이어짐을 확인할 수 있다.
이러한 탐욕적 접근법은 동적 계획법에 비해 구현이 간단하고 실행 시간이 효율적이라는 장점이 있다. 그러나 모든 작업 스케줄링 문제에 탐욕 알고리즘이 최적해를 보장하는 것은 아니다. 문제의 제약 조건과 목표 함수에 따라 적합한 탐욕 선택 기준을 신중하게 설계하고, 그 안전성을 증명하는 것이 중요하다.