기수정렬은 각 동등한 자릿수를 찾아 해당 자릿수를 가지고 배열의 순서를 정하는 방식이다. 효율성이 다른 정렬보다 높을 수 있는 가능성이 상당히 높다.
정렬 방식은 0번째 자릿수(0의자리)를 비교한 후 0~9까지의 순서로 하나씩 배치한다.
그 배치된 새로운 배열을 그 다음은 1번째 자릿수(10의자리)를 비교해 0~9까지 하나씩 배치하며 10보다 작은 숫자는 10의자리의 숫자가 없으므로 0이 되어 여전히 앞자리를 유지하는 방식이다. 결국 10000000이라는 숫자라도 0, 0, 0, 0 ...의 검증을 걸쳐 마지막에 1으로 빠져나가 맨 끝으로 정렬되기 때문에 (더 큰 숫자가 없다면) 최대 숫자의 자릿수를 구한 후 그 숫자의 자릿수까지만 반복 자릿수 검증을 하면 되는 엄청 빠른 방식이다.
단점으로는 양의정수만 가능한 것 같다. (정수로 범위를 넓히면 양의정수의 검증과 음의정수의 검증으로 나눈 후 음의정수는 새 배열에 pop->push를 통해 역순으로 정렬해주면 복잡도에 큰 무리없이 정렬할 수 있을 것 같기는 하다.
기수정렬은 아래와 같다.
function getDigit(num, i) { //num의 i번째 자릿수 구하기 (10의 자릿수라면 10으로 나눈 후 내림을 해서 소숫점을 없앤 후 %10을 통해 나머지만 구할 수 있다.)
return Math.floor(Math.abs(num) / Math.pow(10, i)) % 10;
}
function digitCount(num) { //숫자의 자릿수를 구하는 방식으로 log10을 통해 10의 몇승인지를 구하고 10보다 작은 곱셈값(90 = 9*10)을 버린 다음 1을 더해준다 (10 = 1이지만 10이상은 2자릿수이므로)
if (num === 0) return 1;
return Math.floor(Math.log10(Math.abs(num))) + 1;
}
function mostDigits(nums) { //최고 자릿수를 구하는 방법으로 자릿수를 하나씩 비교해서 최대값만 리턴
let maxDigits = 0;
for (let i = 0; i < nums.length; i++) {
maxDigits = Math.max(maxDigits, digitCount(nums[i]));
}
return maxDigits;
}
function radixSort(nums){ //드디어 본론 기수정렬
let maxDigitCount = mostDigits(nums);
for(let k = 0; k < maxDigitCount; k++){//최대자릿수까지 반복(1,10,100,1000...)
let digitBuckets = Array.from({length: 10}, () => []);//길이10 배열통
for(let i = 0; i < nums.length; i++){//nums(정렬할 숫자배열) 전부 조회
let digit = getDigit(nums[i],k); //nums를 각각 10**k(0~x자릿수)로 자릿수 조회
digitBuckets[digit].push(nums[i]);//조회 자릿수의 숫자 (0번째의 0~9)에 해당하는 배열에 nums[i]넣기
}
nums = [].concat(...digitBuckets); //각 자릿수마다 종료 후 배열 합쳐주기
}
return nums;
}
'회고' 카테고리의 다른 글
| 번들링과 웹팩-2 (0) | 2022.07.26 |
|---|---|
| 번들링과 웹팩 (0) | 2022.07.25 |
| 학습(알고리즘) (0) | 2022.07.23 |
| HTML/CSS 심화-2 (0) | 2022.07.22 |
| HTML/CSS 심화 (0) | 2022.07.21 |
