기타 정렬 - 기수, 계수, 쉘 정렬
2023. 3. 16. 14:16ㆍ알고리즘/정렬
< 개념 >
< 구현 >
1. 기수정렬
// 기수 정렬(radix sort)
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;
public class RadixSort {
public static void radixSort(int[] arr) {
// 0~9까지 크기인 리스트 안에 각 원소가 큐로 이루어진 기수테이블
ArrayList<Queue<Integer>> radixTable = new ArrayList<>();
for (int i = 0; i < 10; i++) {
radixTable.add(new LinkedList<>());
}
int idx = 0;
int div = 1; // 처음 일의자리부터
int maxLen = getMaxLen(arr);
for (int i = 0; i < maxLen; i++) {
// 자리수에 맞게 테이블에 정렬
for (int j = 0; j < arr.length; j++) {
// (arr[j] / div) % 10은 arr[j]의 자리수의 숫자. 즉, 기수테이블에서의 어느 위치 결정
radixTable.get((arr[j] / div) % 10).offer(arr[j]);
}
// 테이블의 값으로 다시 배열에 정렬
for (int j = 0; j < 10; j++) {
Queue<Integer> queue = radixTable.get(j);
while (!queue.isEmpty()) {
arr[idx++] = queue.poll();
}
}
// 다음 자리수 정렬을 위한 세팅
idx = 0;
div *= 10;
}
}
// 최대 자리수 구하기
public static int getMaxLen(int[] arr) {
int maxLen = 0;
for (int i = 0; i < arr.length; i++) {
// log10을 이용하여 숫자 길이 (ex. log1010 = 1 => 10은 두자리 수 이므로 + 1)
int len = (int)Math.log10(arr[i]) + 1;
if (maxLen < len) {
maxLen = len;
}
}
return maxLen;
}
public static void main(String[] args) {
int[] arr = {10,32,52,27,48,17,99,56};
radixSort(arr);
System.out.println("기수 정렬: " + Arrays.toString(arr));
}
}
2. 계수정렬
// 계수정렬
import java.util.Arrays;
public class CountingSort {
public static void countingSort(int[] arr) {
int max = Arrays.stream(arr).max().getAsInt();
int[] cntArr = new int[max + 1];
// counting table에 arr의 값을 위치에 맞게 삽입
for (int i = 0; i < arr.length; i++) {
cntArr[arr[i]]++;
}
// counting table을 arr로 다시 불러와 정렬
int idx = 0;
for (int i = 0; i < cntArr.length; i++) {
while (cntArr[i] > 0) {
arr[idx++] = i;
cntArr[i] -= 1;
}
}
}
public static void main(String[] args) {
int[] arr = {10,32,52,27,48,17,99,56};
countingSort(arr);
System.out.println("계수 정렬: " + Arrays.toString(arr));
}
}
-> arr에 있는 최대값이 너무 말도 안되게 크다면, counting table의 용량도 커져 비효율적!
so, 다른 방법으로 풀면! counting table의 자료구조를 배열 대신 HashMap으로!
// 계수정렬
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
public class CountingSort {
public static void countingSort(int[] arr) {
// 위 counting table은 안 쓰는 공간이 있어 비효율적!
// 배열 대신 HashMap 자료구조로
HashMap<Integer, Integer> map = new HashMap<>();
for (int item: arr) {
map.put(item, map.getOrDefault(item, 0) + 1);
}
int idx2 = 0;
ArrayList<Integer> list = new ArrayList<>(map.keySet());
Collections.sort(list);
for (int i = 0; i < list.size(); i++) {
int cnt = map.get(list.get(i));
while (cnt != 0) {
arr[idx2++] = list.get(i);
cnt--;
}
}
}
public static void main(String[] args) {
int[] arr = {10,32,52,27,48,17,99,56};
countingSort(arr);
System.out.println("계수 정렬: " + Arrays.toString(arr));
}
}
3. 쉘정렬
// 쉘 정렬
import java.util.Arrays;
public class ShellSort {
public static void shellSort(int[] arr) {
int gap = arr.length / 2;
for (int g = gap; g > 0; g /= 2) {
for (int i = g; i < arr.length; i++) {
// gap으로 삽입정렬
int temp = arr[i];
int j = 0;
for (j = i - g; j >= 0; j -= g) {
if (arr[j] > temp) {
arr[j + g] = arr[j];
} else {
break;
}
}
arr[j + g] = temp;
}
}
}
public static void main(String[] args) {
int[] arr = {10,32,52,27,48,17,99,56};
shellSort(arr);
System.out.println("쉘 정렬: " + Arrays.toString(arr));
}
}
'알고리즘 > 정렬' 카테고리의 다른 글
연습문제 - 정렬 (0) | 2023.03.16 |
---|---|
O(nlogn) - 합병, 힙, 퀵, 트리정렬 (0) | 2023.03.08 |
O(n^2) - 선택, 삽입, 버블정렬 (0) | 2023.03.06 |