๐น 5. Sorting
10. ์ ๋ ฌ๊ณผ ํ์
1. ์ ํ ์ ๋ ฌ(selection sort)
โ ํ๊ท ๋ฐ ์ต์ ์คํ ์๊ฐ: $O(n^2)$, ๋ฉ๋ชจ๋ฆฌ: $O(1)$
์ ํ์ ๋ ฌ์ ์ฌํํ์ง๋ง ๋นํจ์จ์ ์ด๋ค.
[ ์ ๋ ฌ ๋ฐฉ๋ฒ ]
- ๋ฐฐ์ด์ ์ ํ ํ์ํ๋ฉฐ ๊ฐ์ฅ ์์ ์์๋ฅผ ๋ฐฐ์ด ๋งจ ์์ผ๋ก ๋ณด๋ธ๋ค.(๋งจ ์์ ์๋ ์์์ ์๋ฆฌ๋ฅผ ๋ฐ๊พผ๋ค.)
- ๊ทธ ๋ค์์ผ๋ก ๋ ๋ฒ์งธ๋ก ์์ ์์๋ฅผ ์ฐพ์ ๋ค ์์ผ๋ก ๋ณด๋ด์ค๋ค.
- ๋ชจ๋ ์์๊ฐ ์ ๋ ฌ๋ ๋๊น์ง ๋ฐ๋ณตํ๋ค.
[ ์ต์ ๊ณผ ์ต์ ์ ๊ฒฝ์ฐ ]
- ์ต์ ์ ๊ฒฝ์ฐ : ์ด๋ฏธ ์ ๋ ฌ๋์ด ์๋ ๊ฒฝ์ฐ๋ฅผ ์๊ฐํด๋ณผ ์ ์๋ค
- ์ต์ ์ ๊ฒฝ์ฐ : ์ญ์์ผ๋ก ์ ๋ ฌ๋์ด ์๋ ๊ฒฝ์ฐ๋ฅผ ์๊ฐํด๋ณผ ์ ์๋ค.
์ ํ ์ ๋ ฌ์ ์ต์ ์ ๊ฒฝ์ฐ์ ์ต์ ์ ๊ฒฝ์ฐ ๋ชจ๋ ํ์์ ํ์๋ $N^2$ ์ด๋ฏ๋ก ๊ฒฐ๊ณผ์ ์ผ๋ก ๋ชจ๋ $O(N^2)$์ ์๊ฐ๋ณต์ก๋๋ฅผ ๊ฐ๋๋ค.
[ ์ฝ๋ ]
1
2
3
4
5
6
7
8
9
10
11
12
13
void selectionSort(int[] arr) {
for (int i = 0; i < N - 1; i++) {
int minIndex = i;
for (int j = i + 1; j < N; j++) {
if (arr[minIndex] > arr[j]) {
minIndex = j;
}
}
int temp = arr[minIndex];
arr[minIndex] = arr[i];
arr[i] = temp;
}
}
2. ์ฝ์ ์ ๋ ฌ(insertion sort)
โ ํ๊ท ๋ฐ ์ต์ ์ ์คํ ์๊ฐ: $O(N^2)$, ๋ฉ๋ชจ๋ฆฌ: $O(1)$
๋ณดํต์ ๊ฒฝ์ฐ ์ฝ์ ์ ๋ ฌ๋ณด๋ค ํต ์ ๋ ฌ์ด ํจ์จ์ ์ด๋ ์ ๋ ฌ์ด ๊ฑฐ์ ๋์ด ์๋ ์ํฉ์์๋ ํต ์ ๋ ฌ ์๊ณ ๋ฆฌ์ฆ๋ณด๋ค ๋ ๊ฐ๋ ฅํ๋ค.
[ ์ ๋ ฌ ๋ฐฉ๋ฒ ]
- ๋ฐฐ์ด์ ์ ํ ํ์ํ๋ฉฐ ํ์ฌ index๊ฐ index ์๊น์ง์ ๋ถ๋ถ์์ ์ฝ์ ๋ ์์น๋ฅผ ์ฐพ์ ์ฝ์ ํ๋ค.
- index๋ฅผ 1์ฉ ํค์ด๋ค.
- ๋ชจ๋ ์์๊ฐ ์ ๋ ฌ๋ ๋๊น์ง ๋ฐ๋ณตํ๋ค.
[ ์ต์ ๊ณผ ์ต์ ์ ๊ฒฝ์ฐ ]
์ต์ ์ ๊ฒฝ์ฐ : ์ด๋ฏธ ์ ๋ ฌ์ด ๋์ด์๋ ๊ฒฝ์ฐ โ $O(N)$
ํ ๋ฒ์ฉ๋ฐ์ ๋น๊ต๋ฅผ ํ์ง ์๊ธฐ ๋๋ฌธ์ $O(N)$
์ต์ ์ ๊ฒฝ์ฐ : ์ญ์์ผ๋ก ์ ๋ ฌ๋ ๊ฒฝ์ฐ โ $O(N^2)$
[ ์ฝ๋ ]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
void insertionSort(int[] arr) {
for (int i = 1; i < N; i++) {
int temp = arr[i];
int prev = i - 1;
for (j = i - 1; j >= 0; j++) {
if (arr[j] > temp) {
arr[j+1] = arr[j];
prev = j;
} else {
break;
}
arr[prev] = temp;
}
}
3. ํ ์ ๋ ฌ(heap sort)
โ ํ๊ท ๋ฐ ์ต์ ์ ์คํ ์๊ฐ: $O(NlogN)$, ๋ฉ๋ชจ๋ฆฌ: $O(1)$
์๊ฐ๋ณต์ก๋๊ฐ $O(NlogN)$์ด๊ธด ํ์ง๋ง ์ค์ ๋ก๋ ๋์ผํ ์๊ฐ ๋ณต์ก๋๋ฅผ ๊ฐ์ง ๋ค๋ฅธ ์ ๋ ฌ ์๊ณ ๋ฆฌ์ฆ(ex. Quick sort)๋ณด๋ค ๋๋ฆฌ๋ค.
[ ์๋ฃ๊ตฌ์กฐ ํ(Heap)์ด๋? ]
: ์์ ์ด์ง ํธ๋ฆฌ์ ์ผ์ข ์ผ๋ก ์ฐ์ ์์ ํ๋ฅผ ์ํด ๋ง๋ค์ด์ง ์๋ฃ๊ตฌ์กฐ
์ฌ๋ฌ ๊ฐ์ ๊ฐ๋ค ์ค์์ ์ต๋๊ฐ๊ณผ ์ต์๊ฐ์ ๋น ๋ฅด๊ฒ ์ฐพ์๋ด๋๋ก ๋ง๋ค์ด์ง ์๋ฃ๊ตฌ์กฐ
- ํ์ ๋ฐ์ ๋ ฌ ์ํ(๋์จํ ์ํ)๋ฅผ ์ ์งํ๋ค
- ํฐ ๊ฐ์ด ์์ ๋ ๋ฒจ์ ์๊ณ , ์์ ๊ฐ์ด ํ์ ๋ ๋ฒจ์ ์์
- ๋ถ๋ชจ ๋ ธ๋์ ํค ๊ฐ์ด ์์ ๋ ธ๋์ ํค ๊ฐ๋ณด๋ค ํญ์ ํฐ(์์) ์ด์ง ํธ๋ฆฌ
- ์ค๋ณต๋ ๊ฐ์ ํ์ฉํ๋ค.
[ ํ(heap) ๊ตฌํ ]
- ํ์ ์ ์ฅํ๋ ํ์ค์ ์ธ ์๋ฃ๊ตฌ์กฐ โ ๋ฐฐ์ด
- ๊ตฌํ์ ์ฝ๊ฒ ํ๊ธฐ ์ํด ์ฒซ ๋ฒ์งธ ์ธ๋ฑ์ค์ธ 0์ ์ฌ์ฉ๋์ง ์๋๋ค.
ํน์ ์์น์ ๋ ธ๋ ๋ฒํธ๋ ์๋ก์ด ๋ ธ๋๊ฐ ์ถ๊ฐ๋์ด๋ ๋ณํ์ง ์๋๋ค.
ex) ๋ฃจํธ ๋ ธ๋์ ์ค๋ฅธ์ชฝ ๋ ธ๋์ ๋ฒํธ๋ ํญ์ 3์ด๋ค.
- ํ์์์ ๋ถ๋ชจ ๋
ธ๋์ ์์ ๋
ธ๋์ ๊ด๊ณ
- ์ผ์ชฝ ์์์ ์ธ๋ฑ์ค = (๋ถ๋ชจ์ ์ธ๋ฑ์ค) * 2
- ์ค๋ฅธ์ชฝ ์์์ ์ธ๋ฑ์ค = (๋ถ๋ชจ์ ์ธ๋ฑ์ค) * 2 + 1
- ๋ถ๋ชจ์ ์ธ๋ฑ์ค = (์์์ ์ธ๋ฑ์ค) / 2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public class Heap<E> {
private final Comparator<? super E> comparator;
private static final int DEFAULT_CAPACITY = 10;
private int size; // ์์ ๊ฐ์
private Object[] array; // ์์๋ฅผ ๋ด์ ๋ฐฐ์ด
// ์์ฑ์ Type 1 (์ด๊ธฐ ๊ณต๊ฐ ํ ๋น X)
public Heap() {
this(null);
}
public Heap(Comparator<? super E> comparator) {
this.array = new Object[DEFAULT_CAPACITY];
this.size = 0;
this.comparator = comparator;
}
// ๋ฐ์ ์ธ๋ฑ์ค์ ๋ถ๋ชจ ๋
ธ๋ ์ธ๋ฑ์ค๋ฅผ ๋ฐํ
private int getParent(int index) {
return index / 2;
}
// ๋ฐ์ ์ธ๋ฑ์ค์ ์ผ์ชฝ ์์ ๋
ธ๋ ์ธ๋ฑ์ค๋ฅผ ๋ฐํ
private int getLeftChild(int index) {
return index * 2;
}
// ๋ฐ์ ์ธ๋ฑ์ค์ ์ค๋ฅธ์ชฝ ์์ ๋
ธ๋ ์ธ๋ฑ์ค๋ฅผ ๋ฐํ
private int getRightChild(int index) {
return index * 2 + 1;
}
}
[ ํ(heap)์ ์ฝ์ ]
- ํ์ ์๋ก์ด ์์๊ฐ ๋ค์ด์ค๋ฉด, ์ผ๋จ ์๋ก์ด ๋ ธ๋๋ฅผ ํ์ ๋ง์ง๋ง ๋ ธ๋์ ์ด์ด์ ์ฝ์ ํ๋ค.
- ์๋ก์ด ๋ ธ๋๋ฅผ ๋ถ๋ชจ ๋ ธ๋๋ค๊ณผ ๊ตํํด์ ํ์ ์ฑ์ง์ ๋ง์กฑ์ํจ๋ค.
1
2
3
4
5
6
7
8
9
10
11
12
13
/* ์ต๋ํ ์ฝ์
*/
void insertMaxHeap(int x) {
maxHeap[++heapSize] = x; // ํ ํฌ๊ธฐ ํ๋๋ฅผ ์ฆ๊ฐํ๊ณ ๋ง์ง๋ง ๋
ธ๋์ x๋ฅผ ๋ฃ๋๋ค
for (int i = heapSize; i > 1; i/=2) {
// ๋ง์ง๋ง ๋
ธ๋๊ฐ ์์ ์ ๋ถ๋ชจ ๋
ธ๋๋ณด๋ค ํฌ๋ฉด swap
if (maxHeap[i/2] < maxHeap[i]) {
swap(i/2, i);
} else {
break;
}
}
}
[ ํ(heap)์ ์ญ์ ]
์ต๋ ํ์์ ์ต๋๊ฐ์ ๋ฃจํธ ๋ ธ๋์ด๋ฏ๋ก ๋ฃจํธ ๋ ธ๋๊ฐ ์ญ์ ๋๋ค.
์ต๋ ํ์์ ์ญ์ ์ฐ์ฐ์ ์ต๋๊ฐ์ ๊ฐ์ง ์์๋ฅผ ์ญ์ ํ๋ ๊ฒ์ด๋ค.
- ์ญ์ ๋ ๋ฃจํธ ๋ ธ๋์๋ ํ์ ๋ง์ง๋ง ๋ ธ๋๋ฅผ ๊ฐ์ ธ์จ๋ค.
- ํ์ ์ฌ๊ตฌ์ฑํ๋ค.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/* ์ต๋ํ ์ญ์ */
int deleteMaxHeap() {
if (heapSize == 0) { //๋ฐฐ์ด์ด ๋น ๊ฒฝ์ฐ
return 0;
}
int item = maxHeap[1]; // ๋ฃจํธ ๋
ธ๋์ ๊ฐ์ ์ ์ฅํ๋ค.
maxHeap[1] = maxHeap[heapSize]; // ๋ง์ง๋ง ๋
ธ๋์ ๊ฐ์ ๋ฃจํธ ๋
ธ๋์ ๋ฃ๋๋ค.
maxHeap[heapSize--] = 0; // ํ ํฌ๊ธฐ๋ฅผ ํ๋ ์ค์ด๊ณ ๋ง์ง๋ง ๋
ธ๋๋ฅผ 0์ผ๋ก ์ด๊ธฐํํ๋ค.
for (int i = 1; i*2 <= heapSize; ) {
// ๋ง์ง๋ง ๋
ธ๋๊ฐ ์ผ์ชฝ ๋
ธ๋์ ์ค๋ฅธ์ชฝ ๋
ธ๋๋ณด๋ค ํฌ๋ฉด ๋ฐ๋ณต๋ฌธ์ ๋๊ฐ๋ค.
if (maxHeap[i] > maxHeap[i*2] && maxHeap[i] > maxHeap[i*2]) {
break;
}
// ์ผ์ชฝ ๋
ธ๋๊ฐ ๋ ํฐ ๊ฒฝ์ฐ, ์ผ์ชฝ ๋
ธ๋์ ๋ง์ง๋ง ๋
ธ๋๋ฅผ swap
else if (maxHeap[i*2] > maxHeap[i*2+1] {
swap(i, i*2);
i = i*2;
}
// ์ค๋ฅธ์ชฝ ๋
ธ๋๊ฐ ๋ ํฐ ๊ฒฝ์ฐ, ์ค๋ฅธ์ชฝ ๋
ธ๋์ ๋ง์ง๋ง ๋
ธ๋๋ฅผ swap
else {
swap(i, i*2+1);
i = i*2+1;
}
}
return item;
}
[ ์ต์ ๊ณผ ์ต์ ์ ๊ฒฝ์ฐ ]
ํ ์ ๋ ฌ์ ์ต์ , ํ๊ท , ์ต์ ๋ชจ๋ O(NlogN)์ ์๊ฐ๋ณต์ก๋๋ฅผ ๊ฐ์ง๋ค.
4. ํต ์ ๋ ฌ(quick sort)
โ ํ๊ท ์คํ ์๊ฐ: $O(NlogN)$, ์ต์ ์คํ ์๊ฐ: $O(N^2)$, ๋ฉ๋ชจ๋ฆฌ: $O(logN)$
์ต์ ์ ๊ฒฝ์ฐ ์คํ์๊ฐ์ด ํ ์ ๋ ฌ๋ณด๋ค ๋๋ฆฌ์ง๋ง ์ผ๋ฐ์ ์ผ๋ก ํต ์ ๋ ฌ์ ์ฌ์ฉํ๋ค.
ํ ์ ๋ ฌ๊ณผ ํต ์ ๋ ฌ ๋ชจ๋ swap์ด ์ฌ์ฉ๋๋๋ฐ ๋ฐ์ดํฐ์ ์์ด ๋ง์ ๋ ํ ์ ๋ ฌ์ด ํจ์ฌ ๋ ๋ง์ swap์ด ์คํ๋๋ฉด์ ์ต์ ์ ๊ฒฝ์ฐ๊ฐ ์๋๋ผ๋ฉด ํต ์ ๋ ฌ์ด ๋ ๋น ๋ฅด๋ค.
[ ์ ๋ ฌ ๋ฐฉ๋ฒ ]
- ๋ฌด์์๋ก ์ ์ ๋ ํ ์์๋ฅผ ์ฌ์ฉํ์ฌ ๋ฐฐ์ด์ ๋ถํ ํ๋ค.
์ ์ ๋ ์์๋ณด๋ค ์์ ์์๋ค์ ์์, ํฐ ์์๋ค์ ๋ค๋ก ๋ณด๋ธ๋ค.
๋ฐฐ์ด ๋ถํ ์์ ์ ์ฐ์๋ swap ์ฐ์ฐ์ ํตํด ํจ์จ์ ์ผ๋ก ์ํ๋๋ค
๋ฐฐ์ด๊ณผ ๊ทธ ๋ถ๋ถ ๋ฐฐ์ด์ ๋ฐ๋ณต์ ์ผ๋ก ๋ถํ ํด ๋๊ฐ๋ฉด ๊ฒฐ๊ตญ์ ๋ฐฐ์ด์ ์ ๋ ฌ๋ ์ํ์ ๋๋ฌํ๋ค.
ํ์ง๋ง ๋ฐฐ์ด ๋ถํ ์ ์ฌ์ฉ๋๋ ์์๊ฐ ์ค๊ฐ๊ฐ, ์ ์ด๋ ์ค๊ฐ๊ฐ์ ๊ฐ๊น์ด ๊ฐ์ด ๋๋ฆฌ๋ผ๋ ๋ณด์ฅ์ด ์๊ธฐ ๋๋ฌธ์, ์ ๋ ฌ ์๊ณ ๋ฆฌ์ฆ์ด ๋๋ฆฌ๊ฒ ๋์ํ ์๋ ์๋ค.
[ ์ต์ ๊ณผ ์ต์ ์ ๊ฒฝ์ฐ ]
- ์ต์ ์ ๊ฒฝ์ฐ : pivot ๊ฐ์ด ์ต์๋ ์ต๋๊ฐ์ผ๋ก ์ง์ ๋์ด ํํฐ์ ์ด ๋๋์ด์ง์ง ์์์ ๋ โ $O(N^2)$
[ ์ฝ๋ ]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
void quickSort(int[] arr, int left, int right) {
int index = partition(arr, left, right);
if (left < index - 1) { // ์ผ์ชฝ ์ ๋ฐ ์ ๋ ฌ
quickSort(arr, left, index - 1);
}
if (index < right) { // ์ค๋ฅธ์ชฝ ์ ๋ฐ ์ ๋ ฌ
quickSort(arr, index, right);
}
}
int partition(int[] arr, int left, int right) {
int pivot = arr[(left + right) / 2]; // ๋ถํ ๊ธฐ์ค ์์ ์ ์
while (left <= right) {
// ์ผ์ชฝ์์ ์ค๋ฅธ์ชฝ์ผ๋ก ์ฎ๊ฒจ์ผ ํ๋ ์์ ํ์
while (arr[left] < pivot) left++;
// ์ค๋ฅธ์ชฝ์์ ์ผ์ชฝ์ผ๋ก ์ฎ๊ฒจ์ผ ํ๋ ์์ ํ์
while (arr[right] > pivot) right--;
// ์์๋ฅผ ์ค์ํ ๋ค left์ right๋ฅผ ์ด๋
if (left <= right) {
swap(arr, left, right); // ์ค์
left++;
right--;
}
}
return left;
}
5. ๋ณํฉ ์ ๋ ฌ(merge sort)
โ ํ๊ท ๋ฐ ์ต์ ์คํ ์๊ฐ: $O(NlogN)$, ๋ฉ๋ชจ๋ฆฌ: ์ํฉ์ ๋ฐ๋ผ ๋ค๋ฆ
๋ฐฐ์ด์ ๋ถํ ํ๋ค๊ฐ โ๋ณํฉโ์ ์ฒ๋ฆฌํ๋ ๊ณผ์ ์ด ๊ฐ์ฅ ๋ณต์กํ๋ค.
[ ๋ณํฉ ์์ ]
- ๋ณํฉ ๋์์ด ๋๋ ๋ฐฐ์ด์ ๋ ๋ถ๋ถ์ ์์ ๋ฐฐ์ด(helper)์ ๋ณต์ฌํ๋ค.
- ์ผ์ชฝ ์ ๋ฐ์ ์์ ์ง์ (helperLeft)์ ์ค๋ฅธ์ชฝ ์ ๋ฐ์ ์์ ์ง์ (helperRight)๋ฅผ ์ถ์ ํ๋ค.
- helper๋ฅผ ์ํํ๋ฉด์ ๋ ๋ฐฐ์ด์์ ๋ ์์ ๊ฐ์ ์์๋ฅผ ๊บผ๋ด์ด ์๋ ๋ฐฐ์ด์ ๋ณต์ฌํด ๋ฃ๋๋ค.
- ๋ ๋ฐฐ์ด ์ค ํ ๋ฐฐ์ด์ ๋ํ ์ํ๊ฐ ๋๋ ๊ฒฝ์ฐ์๋ ๋ค๋ฅธ ๋ฐฐ์ด์ ๋จ์ ๋ถ๋ถ์ ์๋ ๋ฐฐ์ด์ ๋จ๊น์์ด ๋ณต์ฌํด ๋ฃ๊ณ ์์ ์ ๋ง์น๋ค.
[ ์ฝ๋ ]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
void mergesort(int[] array) {
int[] helper = new int[array.length];
mergesort(array, helper, 0, arraay.length - 1);
}
void mergesort(int[] array, int[] helper, int low, int high) {
if (low < high) {
int middle = (low + high) / 2;
mergesort(array, helper, low, middle); // ์ผ์ชฝ ์ ๋ฐ ์ ๋ ฌ
mergesort(array, helper, middle+1, high); // ์ค๋ฅธ์ชฝ ์ ๋ฐ ์ ๋ ฌ
merge(array, helper, low, middle, high); // ๋ณํฉ
}
}
void merge(int[] array, int[] helper, int low, int middle, int high) {
/* ์ ๋ฐ์ง๋ฆฌ ๋ ๋ฐฐ์ด์ helper ๋ฐฐ์ด์ ๋ณต์ฌํ๋ค. */
for (int i = low; i <= high; i++) {
helper[i] = array[i].
}
int helperLeft = low;
int helperRight = middle + 1;
int current = low;
/* helper ๋ฐฐ์ด ์ํ. ์ผ์ชฝ ์ ๋ฐ๊ณผ ์ค๋ฅธ์ชฝ ์ ๋ฐ์ ๋น๊ตํ์ฌ ์์ ์์๋ฅผ
* ์๋ ๋ฐฐ์ด์ ๋ณต์ฌํด ๋ฃ๋๋ค. */
while (helperLeft <= middle && helperRight <= high) {
if (helper[helperLeft] <= helper[helperRight]) {
array[current] = helper[helperLeft];
helperLeft++;
} else { // ์ค๋ฅธ์ชฝ ์์๊ฐ ์ผ์ชฝ ์์๋ณด๋ค ์์ผ๋ฉด
array[current] = helper[helperRight];
helperRight++;
}
current++;
}
/* ์ผ์ชฝ ์ ๋ฐ ๋ฐฐ์ด์ ๋จ์ ์์๋ค์ ์๋ ๋ฐฐ์ด์ ๋ณต์ฌํด ๋ฃ๋๋ค. */
int remaining = middle - helperLeft;
for (int i = 0; i <= remaining; i++) {
array[current + i] = helper[helperLeft + i];
}
}