01. 퀵정렬 (quick sort)
퀵 정렬은 일반적으로 사용되고 있는 아주 빠른 정렬 알고리즘이다. 분할 정복 알고리즘의 하나이다.
- 퀵 정렬은 한 요소인
피벗(pivot)
을 지정하여 기준점으로 잡는다.
- 불안정 정렬에 속하며, 다른 원소와의 비교만으로 정렬을 수행하는 비교 정렬에 속한다.
- 분할 정복 알고리즘의 한 종류로, 평균적으로 매우 빠른 속도를 가진다.
- 퀵 정렬은 n개의 데이터를 정렬할 때, 최악의 경우에는 O(n2)번의 비교를 수행하고, 평균적으로 O(n log n)번의 비교를 수행한다.
퀵정렬은 다음과 같은 순서로 이루어진다.
- 리스트 중에서 하나의 원소를 고른다. 이 원소를 피벗(pivot) 으로 지정한다.
- 피벗 앞으로는 피벗보다 값이 작은 원소들이 오고, 뒤로는 피벗보다 값이 큰 원소들이 오도록 피벗을 기준으로 리스트를 둘로 나눈다.
- 리스트가 둘로 나뉘는 것을 분할 이라한다.
- 분할을 마친 뒤, 피벗은 더 이상 움직이지 않는다.
- 분할된 두 리스트에 대해 재귀적으로 위 과정을 반복한다. (리스트의 크기가 1 이하일 떄 까지)
퀵정렬 - 예시
- 피벗은 p, 리스트 왼쪽 끝과 오른쪽 끝에서 시작한 인덱스들을 l, r
5 - 3 - 7 - 6 - 2 - 1 - 4
p
- 리스트 왼쪽에 있는
l
위치의 값이 피벗 값보다 크고, 오른쪽에 있는 r
위치의 값은 피벗 값보다 작으므로 둘을 교환한다.
5 - 3 - 7 - 6 - 2 - 1 - 4
l r p
1 - 3 - 7 - 6 - 2 - 5 - 4
l r p
r
위치의 값이 피벗 값보다 작지만, l
위치의 값도 피벗값보다 작으므로 교환하지 않는다.
1 - 3 - 7 - 6 - 2 - 5 - 4
l r p
l
위치를 피벗 값보다 큰 값이 나올 때까지 진행해 r
위치의 값과 교환한다.
1 - 3 - 7 - 6 - 2 - 5 - 4
l r p
1 - 3 - 2 - 6 - 7 - 5 - 4
l r p
l
위치가 r
위치보다 커지면, l 위치의 값과 피벗 값을 교환
한다.
1 - 3 - 2 - 6 - 7 - 5 - 4
p
1 - 3 - 2 - 4 - 7 - 5 - 6
p
- 피벗 값 좌우의 리스트에 대해 각각 퀵 정렬을 재귀적으로 수행한다.
1 - 3 - 2 7 - 5 - 6
1 - 2 - 3 5 - 6 - 7
- 완성된 리스트는 다음과 같다.
1 - 2 - 3 - 4 - 5 - 6 - 7
퀵정렬 특징
장점
- 속도가 빠르다.(퀵!)
- 시간 복잡도 O(nlogn)을 가진 다른 정렬알고리즘과 비교했을 때도 가장 빠름.
- 추가 메모리 공간이 필요하지 않음.
단점
- 정렬된 리스트에 대해서는 퀵정렬 분할로 인해 수행시간이 더 소요된다.
- 퀵정렬 불균형 분할을 방지하기 위해 피벗을 선택할 때 신중해야한다.
- 단점을 해결하기 위해서 임의의 요소를 선택 후 중간 값을 선택하는 식으로 피벗을 선택.
시간복잡도
- 최선의 경우 n만큼 파티션을 나누는데 그때 마다 데이터가 절반씩 줄어들어서 O(nlogn)
- 최악의 경우 O(n2) 을 가지게 된다.
- 순환 호출의 깊이가 n
- 특히 이미 정렬된 리스트에 대하여 퀵정렬을 시도하는 경우.
- 순환 호출 깊이 * 각 순환 호출 단계 비교연산 = n2
- 평균적으로 O(nlogn) 이다.
- 시간복잡도 O(nlogn)인 다른 정렬알고리즘과 비교했을 떄도 가장 빠르다.
- 불필요한 데이터 이동을 줄이고, 한번 결정된 피벗은 추후 연산에 사용되지 않기 떄문.
02. 힙정렬 (heap sort)
최대 힙 트리나 최소 힙 트리를 구성해 정렬하는 알고리즘
힙은 완전이진트리의 일종이며 최솟값, 최대값을 쉽게 추출할 수 있는 구조이다.
배열로 최대 힙을 구성한 뒤 정렬하는 순서이다.
- n개의 노드에 대한 완전이진트리를 구성한다. 루트를 기준으로 부모, 왼쪽자식, 오른쪽자식 순서로 구성
- 최대 힙을 구성한다. 최대 힙이란 부모노드가 자식노드보다 큰 트리를 말한다.
- 아랫부분의 작은 부분트리부터 시작해 올라가는 방식(bottom-up)으로 전체 배열을 최대 힙으로 만든다.
- 힙에서 가장 큰 값인 루트를 배열의 가장 마지막 값과 바꾼다. (마지막에 가장 큰 수인 루트가 정렬)
- 다시 힙의 구조가 유지되도록 정리한다.
- 4~5번 작업을 모든 숫자가 완료 상태가 될 때까지 반복
힙정렬 - 예시
출처 : https://ko.wikipedia.org/wiki/%ED%9E%99_%EC%A0%95%EB%A0%AC
힙정렬 특징
장점
- 시간복잡도가 좋은편
- 힙정렬이 유용한 경우는 전체 자료 정렬보다 가장 큰 값 몇 개만 필요한 경우
시간복잡도
- 이진 트리를 최대 힙으로 만들기 위하여 최대 힙으로 재구성하는 과정이 트리의 깊이만큼 -> O(logn)
- 요소의 개수 n개 이므로 O(nlogn) 의 시간복잡도를 가진다.
03. 위상정렬 (topological sort)
순서가 정해져있는 작업을 차례로 수행해야 할 때 그 순서를 결정하기 위해 사용하는 알고리즘
- 사이클이 없는 방향 그래프(DAG) 의 모든 노드를 방향성에 거스르지 않도록 순서대로 나열을 한다.
- 위상정렬은 DFS를 이용해서 구현할 수 있으며, 큐를 이용해서 구현할 수도 있다.
큐를 이용한 위상정렬의 순서는 다음과 같다.
- 진입차수가 0인 모든 노드를 큐에 넣는다.
- 큐가 빌 때까지 다음의 과정을 반복한다.
- 큐에서 원소를 꺼내 해당 노드에서 나가는 간선을 그래프에서 제거
- 새롭게 진입차수가 0이 된 노드를 큐에 넣기
- 각 노드가 큐에 들어온 순서가 위상정렬 수행 결과
위상정렬 - 예시
출처 : https://guides.codepath.com/compsci/Topological-Sort#implementation
관련 예시
- 각각의 작업이 완료되어야만 끝나는 프로젝트
- 선수 과목
위상정렬 특징
References