1일 1개념정리 24.08.09.금 ~
큰 결정에 큰 동기가 따르지 않을 때도 있다. 하지만 큰 결심이 따라야 이뤄낼 수 있다.
무조건 무조건 1일 1개의 개념 정리하기 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
#64. 안정 정렬
어제는 정렬 알고리즘의 기본 개념 중, 안정성과 제자리성에 대해서 알아보았다. 그 중 오늘은 안정성을 만족하는 정렬들에 대해서 알아보자. 삽입, 버블, 합병 뿐만 아니라 계수, 기수 정렬도 있지만 뒤에 2개는 약간 마이너한 느낌이 들어서..... 앞에 3개만 정리해보려 한다. 시간이 없는 것은 아님

제자리성 | 안정성 | 최선 시간복잡도 | 평균 시간복잡도 | 최악 시간복잡도 | |
삽입 정렬 | O | O | O(n) | O(n²) | O(n²) |
선택 정렬 | O | X | O(n²) | O(n²) | O(n²) |
버블 정렬 | O | O | O(n) | O(n²) | O(n²) |
셸 정렬 | O | X | O(n) | O(n^1.5) | O(n²) |
퀵 정렬 | O | X | O(n log n) | O(n log n) | O(n²) |
병합 정렬 | X (메모리 사용) | O | O(n log n) | O(n log n) | O(n log n) |
힙 정렬 | O | X | O(n log n) | O(n log n) | O(n log n) |
기수 정렬 | X (메모리 사용) | O | O(nk) | O(nk) | O(nk) |
계수 정렬 | X (메모리 사용) | O | O(n + k) | O(n + k) | O(n + k) |
삽입 정렬 (Insertion Sort)
배열을 두번째 인덱스 부터 시작해서 앞의 원소들과 비교하며 정렬된 부분으로 삽입하는 것이다.
EX) [4, 2, 7, 1, 3]
- 두번째 인덱스부터 시작함. 1번째 인덱스를 "정렬된 부분"으로 표현.
- 두 번째 원소(2)를 앞의 정렬된 부분에 삽입 = [2, 4, 7, 1, 3]
- 세 번째 원소(7)를 정렬된 부분에 넣으려고 보니, 이미 내 자리에 와있음. = [2, 4, 7, 1, 3]
- 네 번째 원소(1)를 정렬된 부분에 삽입 = [1, 2, 4, 7, 3]
- 다섯 번째 원소(3)를 정렬된 부분에 삽입 = [1, 2, 3, 4, 7]
def insertion_sort(arr):
# 두 번째 요소부터 시작하여 정렬된 부분에 삽입
for i in range(1, len(arr)):
key = arr[i] # 현재 요소를 임시 변수에 저장
j = i - 1
# 정렬된 부분에서 현재 요소보다 큰 요소를 오른쪽으로 이동
while j >= 0 and arr[j] > key:
arr[j + 1] = arr[j]
j -= 1
# 현재 요소를 정렬된 부분의 적절한 위치에 삽입
arr[j + 1] = key
return arr
arr = [4, 2, 7, 1, 3]
sorted_arr = insertion_sort(arr)
print("삽입 정렬된 배열:", sorted_arr)
버블 정렬 (Bubble Sort)
배열의 첫 번째 인덱스부터 시작하여 "인접한" 두 요소를 비교하며 정렬하는 방식이다. 같은 값의 원소는 위치를 바꾸지 않으므로 안정성을 만족한다. 매 회전마다 최대값이 뒤로 이동한다는 것이 큰 특징 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 5,4,3,2,1을 정렬하면 1번째 정렬때 5가 맨 뒤로 가고, 두번째 정렬땐 4가 뒤로 가서 ~~~ 4, 5가 되고 그 다음에는 ~~~ 3, 4, 5가 되고 .... 이런 식
EX) [5, 3, 8, 4, 2]
1) 첫번째 회전.
- 5와 3 비교 → [3, 5, 8, 4, 2]
- 5와 8 비교 → [3, 5, 8, 4, 2]
- 8과 4 비교 → [3, 5, 4, 8, 2]
- 8과 2 비교 → [3, 5, 4, 2, 8] (8이 맨 뒤로 이동)
2) 두번째 회전.
- 3과 5 비교 → [3, 5, 4, 2, 8]
- 5와 4 비교 → [3, 4, 5, 2, 8]
- 5와 2 비교 → [3, 4, 2, 5, 8] (5가 뒤로 이동)
3) 세번째 회전.
- 3과 4 비교 → [3, 4, 2, 5, 8]
- 4와 2 비교 → [3, 2, 4, 5, 8] (4가 뒤로 이동)
4) 네번째 회전.
- 3과 2 비교 → [2, 3, 4, 5, 8] (완료)
def bubble_sort(arr):
n = len(arr)
# 배열의 끝까지 반복
for i in range(n):
# 인접한 요소들을 비교하고 교환
for j in range(0, n - i - 1):
if arr[j] > arr[j + 1]:
# 순서가 잘못된 경우 두 요소를 교환
arr[j], arr[j + 1] = arr[j + 1], arr[j]
return arr
# 예제 실행
arr = [5, 3, 8, 4, 2]
sorted_arr = bubble_sort(arr)
print("버블 정렬된 배열:", sorted_arr)
병합 정렬 (Merge Sort)
병합 정렬은 배열을 재귀적으로 반으로 나누고, single element까지 나눈 뒤, 정렬된 두 부분을 병합하면서 전체 배열을 정렬해나가는 방식이다. "Divide and Conquer" 방식으로, 쪼개고 합치며 정복하는 것이다.
EX) [5, 2, 4, 7, 1, 3, 6]
- 배열을 반으로 나눔 = [5, 2, 4, 7] / [1, 3, 6]
- 나눈 배열을 다시 반으로 나눔 = [5, 2] / [4, 7] / [1, 3] / [6]
- 단일 요소가 될 때까지 나눔 = [5] / [2] / [4] / [7] / [1] / [3] / [6]
- 병합하며 정렬한다. 5랑 2 비교했더니 2가 크니깐 2, 5로 합쳐주는 방식, 나머지도 똑같음. = [2, 5] / [4, 7] / [1, 3] / [6] ////// 요기 합쳐지는 과정이 이해 안될 수 있는데, 아래 코드로 보자. [2,5]랑 [4,7] 합칠 때 첫번째 원소끼리 비교해서 2, 4중에 2가 작으깐 빈 리스트에 2를 넣는 방식이다. 그럼 [5]랑 [4,7]이 남았으니, 다시 첫번째 원소인 5랑 4를 비교한다. 4가 더 작으니깐 4를 넣어준다. 그럼 정렬 리스트는 [2,4]고 이제 남은 것은 [5], [7]이다. 이것도 같은 방식으로 정렬. 이런식으로 정렬한다. (합병시 매번 맨 앞의 원소끼리 비교.)
- 계속 합쳐줌. 합칠 때 정렬함. = [2, 4, 5, 7] / [1, 3, 6]
- 완료. [1, 2, 3, 4, 5, 6, 7]
def merge_sort(arr):
# 배열의 길이가 1 이하이면 이미 정렬된 상태이므로 그대로 반환
if len(arr) <= 1:
return arr
# 배열을 중간 지점에서 나누기
mid = len(arr) // 2
left_half = arr[:mid]
right_half = arr[mid:]
# 재귀적으로 좌우 반을 정렬
left_sorted = merge_sort(left_half)
right_sorted = merge_sort(right_half)
# 정렬된 좌우 반을 병합
return merge(left_sorted, right_sorted)
def merge(left, right):
# 병합된 결과를 저장할 배열
result = []
i = j = 0
# 두 배열을 비교하며 작은 요소를 결과에 추가
while i < len(left) and j < len(right):
if left[i] <= right[j]:
result.append(left[i])
i += 1
else:
result.append(right[j])
j += 1
# 남은 요소들을 결과 배열에 추가
# 왼쪽 배열에 남은 요소가 있다면 추가
while i < len(left):
result.append(left[i])
i += 1
# 오른쪽 배열에 남은 요소가 있다면 추가
while j < len(right):
result.append(right[j])
j += 1
# 병합된 결과 반환
return result
# 예제 실행
arr = [5, 2, 4, 7, 1, 3, 6]
sorted_arr = merge_sort(arr)
print("정렬된 배열:", sorted_arr)
'1일 1개념정리 (24년 8월~12월) > 자료구조' 카테고리의 다른 글
1일1개 (82) - 무질서속의 질서 (1) | 2024.11.15 |
---|---|
1일1개 (65) - 불안정 정렬 (1) | 2024.10.20 |
1일1개 (63) - 제자리성, 안정성 (0) | 2024.10.17 |
1일1개 (45) - 자료구조의 힙합 (1) | 2024.09.29 |