일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 백준
- DP
- dbms
- 브라우저
- 순열 알고리즘
- programmers
- 정렬 알고리즘
- SERVLET
- 다이나믹 프로그래밍
- jsp
- 소수
- request
- 네이버 부스트캠프 ai tech
- 프로그래머스
- greedy
- 크루스칼 알고리즘
- mysql
- 그리디
- 웹 프로그래밍
- 해시
- 웹프로그래밍
- mst
- 웹서버
- Prim's Algorithm
- 부스트코스
- 벡엔드
- BJ
- 프림 알고리즘
- 정렬
- Kruskal's Algorithm
- Today
- Total
끵뀐꿩긘의 여러가지
Java - 정렬 알고리즘 - 6 (계수 정렬) 본문
◎계수 정렬
정수들로 이루어진 배열을 원소들의 비교를 하지않고, 최소값과 최대값 사이에 존재하는 원소의 개수를 세어서 정렬하는 방식
◎계수 정렬의 특징
1. 비교 정렬(comparison sort)이 아니다
계수정렬은 데이터를 비교하면서 찾지 않는다
2. 제자리 정렬(in-place sort)이 아님
정렬의 대상이 되는 데이터 외에 추가적인 공간을 필요로 한다
3. 안정 정렬(stable sort)
정렬되지 않은 상태에서 같은 키값을 가진 원소의 순서가 정렬 후에도 유지된다.
◎계수 정렬의 동작
※계수 정렬은 원소들의 최댓값과 최솟값을 안다는 가정하에 실행된다
1. 배열 내에 원소 값들의 갯수를 저장하는 카운팅 배열을 만든다.
- 카운팅 배열의 길이는 '원소들의 최댓값 - 원소들의 최소값 + 1'이다.
(ex. 최댓값이 5, 최솟값이 0이라면 카운팅 배열의 길이는 6이다.)
2. 배열을 idx 순서대로 살펴보면서 원소가 나온 횟수를 카운팅 배열에 누적시킨다.
(ex. [2,4,2]인 배열이 있다면, 최댓값이 4, 최솟값이 2이므로 카운팅 배열의 길이는 3이고, 2가 2번 4이 1번 나오므로
카운팅 배열은 [2,0,1]의 값을 가진다)
3. 카운팅 배열에 대해서 직전 요소들의 값을 더해준다.
(ex. 카운팅 배열이 현재 [2,0,1]이므로, 직전 요소들의 값을 더해주면, [2,2,3]([2,2+0,2+1])이 된다.)
4. 입력 배열과 동일한 크기의 출력배열을 만들고 입력 배열의 역순으로 요소들을 채워 넣어준다.
(ex.
원래 배열이 [2,4,2],
카운팅 배열이 [2,2,3],
출력 배열의 크기는 원래 배열과 동일한 3
카운팅 배열에 따라 2가 2개 4이 1개가 있으므로, 출력배열은 [2,2,4]
)
◎계수 정렬의 구현
package SortAlgorithm;
public class sort {
//계수 정렬
private void countingsort(int[] numarr, int max, int min) {
// 카운팅 배열 길이 = 원소들의 최댓값 - 원소들의 최소값 + 1
final int counting_length = max - min +1;
int[] counting = new int[counting_length];
//출력 배열의 길이 = 입력 배열의 길이
int[] output = new int[numarr.length];
//카운팅 배열에 원소들의 출현 횟수 누적
for(int i = 0; i<numarr.length; i++) {
counting[numarr[i]-min]++;
}
//직전 요소들의 값 더해줌
for(int i = 1; i<counting.length; i++) {
counting[i] = counting[i] + counting[i -1];
}
//입력 배열의 역순으로 요소들을 출력배열에 채워 넣어준다
for(int i = numarr.length-1; i>=0; i--) {
/*
* counting 배열에서 1번 출현한 원소는 1로 표현되므로,
* output배열의 index로 사용할때 --연산자를 통해 미리 -1을 해준다.
* numarr[i]-min을 통해 counting 배열의 index 0에 있는 값이
* 원래 배열 최솟값의 출현횟수가 되도록 조정한다
*/
output[--counting[numarr[i]-min]] = numarr[i];
}
print(output, "계수 정렬");
}
// 출력
private void print(int[] numarr, String sortname) {
System.out.println(sortname + "로 정렬된 배열:" + Arrays.toString(numarr));
}
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] numarr = { -1 ,5, 6, 3, 1, 4, 2 }; // 정렬할 배열
System.out.println("원래 배열:" + Arrays.toString(numarr));
sort Sort = new sort();
Sort.countingsort(numarr,6,-1);
}
}
실행 결과:
원래 배열:[-1, 5, 6, 3, 1, 4, 2]
계수 정렬로 정렬된 배열:[-1, 1, 2, 3, 4, 5, 6]
◎계수 정렬의 시간복잡도 공간복잡도
계수 정렬의 시간복잡도는 O(n+k)(k는 최댓값 - 최솟값 +1)으로, 빅-오 표기법 상으로는 O(n)이고, 모든 비교 정렬(comparison sort)보다 빠른 정렬 방식이다. 하지만, 극단적으로 정렬해야할 배열이 [1억, 1]으로 정렬해야할 배열의 크기보다 수의 범위가 심히 클 때, counting 배열의 길이 k=1억으로 카운팅 배열을 생성하고 직전요소를 더해 카운팅 배열을 완성하는 과정이 매우 오래 걸리고 공간효율성도 매우 떨어진다.
◎Sorting algorithm 시간 복잡도(time complexity) & 평균 정렬 속도(average sorting rate)
◆기수 정렬의 시간복잡도는 O(dn)이고, 계수정렬의 시간복잡도가 O(n+k)이다.◆
◎정렬 알고리즘 구현-github
github.com/jerry-ryu/java_problemsolving_algorithm/tree/main/sorting_algorithm
jerry-ryu/java_problemsolving_algorithm
solving problems and learning algorithm using java - jerry-ryu/java_problemsolving_algorithm
github.com
'JAVA > 자료구조-알고리즘&함수 정리' 카테고리의 다른 글
Java - 정렬 알고리즘 - 8 (셸 정렬) (0) | 2021.05.22 |
---|---|
Java - 정렬 알고리즘 - 7 (퀵 정렬) (0) | 2021.05.22 |
Java - 정렬 알고리즘 - 5 (힙 정렬) (0) | 2021.05.19 |
Java - 정렬 알고리즘 - 4 (병합 정렬) (0) | 2021.05.10 |
Java - 정렬 알고리즘 - 3 (선택 정렬) (0) | 2021.05.10 |