알고리즘 10강을 보며 배운내용
정리(TL;DR)
밑의 4가지 정렬 모두 시간 복잡도 On2
1. 버블 정렬
1. 인접한 두 값 비교
2. 왼쪽 값이 크면 자리 바꾸기
안정적 정렬 ✅
제자리 정렬 ✅
2. 선택 정렬
1. 최솟값 찾고
2. 작은 값부터 나열
안정적 정렬 ❌
제자리 정렬 ✅
3. 삽입 정렬
1. 정렬 부분(첫 번째 값), 미정렬 부분(두 번째 값부터)으로 잡고
2. 정렬 부분 뒤부터 비교
3. 정렬 부분의 값보다 크거나 같으면 오른쪽에 삽입
안정적 정렬 ✅
제자리 정렬 ✅
4. 셸 정렬
삽입 정렬을 개선하고자 나온 정렬
삽입 정렬을 크기가 변하는 부분 배열로 실행
안정적 정렬 ❌
제자리 정렬 ✅
정렬
- 내부 정렬
모든 데이터가 주기억장치에 저장 - 외부 정렬
보조기억장치에 저장하고 필요할 때 주기억장치로 가져온다
내부 정렬 알고리즘
비교 기반, 데이터 분포 기반
1. 비교 기반
- 일반적으로 비교 기반 사용
- 키값의 비교 횟수
버블, 선택, 삽입, 셸
⌛ O(n2)
합병, 퀵, 힙
⌛ O(nlogn)
2. 데이터 분포 기반
- 데이터를 분포 상태를 알고 있을 때
- 데이터 이동 횟수
계수, 기수
⌛ O(n)
안정적(Stable) 정렬
동일한 값을 갖느 데이터 여러개 있을 때
정렬 후에도 순서 유지
제자리(In-place) 정렬
추가적인 저장 공간 증가하지 않는 것
버블 정렬
- 인접한 두 값을 비교해서
- 왼쪽 값이 큰 경우 자리 바꾸는 과정 반복
✨ 특징
안정적 & 제자리 정렬 알고리즘
입력 데이터가 역순일 때 가장 성능이 떨어진다
버블 정렬이 한 번 돌아갈 때(한 번 '패스'라고 한다)
왼쪽에서 오른쪽으로 진행하면
➡️ 가장 큰 값이 맨 오른쪽에 위치
오른쪽에서 왼쪽으로 진행하면
➡️ 가장 작은 값이 맨 왼쪽에 위치
🤖 코드
// 버블정렬
function bubbleSort(배열, n){
for(let i = 0; i < n - 1; i++) {
for(let j = 0; j < (n - 1) - i; j++) {
// 왼쪽이 크면 자리 바꾸기
if(배열[j] > 배열[j+1]) {
[배열[j], 배열[j+1] = [배열[j+1], [배열[j]]
}
}
}
return 배열
}
🦾🤖 개선된 코드
// 개선된 버블정렬
function bubbleSort(배열, n){
let exchange = false
for(let i = 0; i < n - 1; i++) {
exchange = false
for(let j = 0; j < (n - 1) - i; j++) {
// 왼쪽이 크면 자리 바꾸기
if(배열[j] > 배열[j+1]) {
[배열[j], 배열[j+1] = [배열[j+1], [배열[j]]
exchange = true
}
}
if(!exchange) break;
}
return 배열
}
자리 바꿈이 일어나지 않으면 반복문을 나오게 만들어줬다
선택 정렬
가장 작은 값부터 차례대로 선택해서 나열
✨ 특징
언제나 동일한 시간 복잡도
제자리 정렬 알고리즘
🤖 코드
// 선택 정렬
function selectionSort(배열, n) {
for(let i = 0; i < n - 1; i++) {
let 최솟값 = i;
// 우선 최솟값 찾기
for(let j = i + 1; j < n; j++) {
if(배열[최솟값] > 배열[j] {
최솟값 = j
}
}
// 첫 번째 원소와 최솟값 교환
[배열[i], 배열[최솟값]] = [배열[최솟값], 배열[i]]
}
return 배열
}
삽입 정렬
데이터 하나씩 뽑아서 바른 위치에 삽입해서 나열
- 정렬 부분과 미정렬 부분으로 구분하고
- 미정렬 부분에서 첫 번째 데이터 뽑고
- 정렬 부분에서 들어갈 위치에 삽입
➡️ 정렬 부분 뒤부터 비교하면서 넣어주면 된다
✨ 특징
안정적 & 제자리 정렬
데이터 하나씩 비교하는 비효율 가지고 있다
➡️ 그래서 나온 셸 정렬
🤖 코드
// 삽입 정렬
function insertionSort(배열, n) {
let i, j
for(i = 1; i < n; i++) {
let 첫번째데이터 = 배열[i]
for(j = i; j > 0 && 배열[j - 1] > 첫번째데이터; j++) {
배열[j] = 배열[j - 1]
}
배열[j] = 첫번째데이터
}
return 배열
}
i = 1부터 하는 이유는 첫 번째 데이터를 정렬 데이터로 취급
셸 정렬
삽입 정렬의 단점 보완
멀리 떨어진 데이터와 비교/교환
부분 배열로 나눠서 삽입 정렬 수행
부분 배열 크기와 개수 변화시키면서 반복
✨ 특징
제자리 정렬 알고리즘
🤖 코드
// 셸 정렬
function shellSort(배열, n) {
let i, j, val
for(let D = n / 2; D >= 1; D = D / 2) {
for(i = D; i < n; i++) {
val = 배열[i]
for(j = i; j >= D && 배열[j - D] > val; j = j - D) {
배열[j] = 배열[j - D]
}
배열[j] = val
}
}
}
'Computer Science > Algorithm :: 알고리즘' 카테고리의 다른 글
알고리즘 12강 :: 순차 탐색, 이진 탐색, 이진 탐색 트리 (0) | 2022.03.31 |
---|---|
알고리즘 11강 :: 합병 정렬, 퀵 정렬, 힙 정렬 (0) | 2022.03.24 |
알고리즘 9강 :: 알고리즘 목차, 분할정복, 동적프로그래밍, 욕심쟁이 (0) | 2022.03.04 |
알고리즘 8강 :: 욕심쟁이, 최단경로, 작업스케쥴, 작업 선택 (0) | 2022.03.03 |
알고리즘 7강 :: 욕심쟁이, 동전거스름돈, 배낭문제, 신장트리 (0) | 2022.03.02 |