- 이웃한 원소를 비교하고, 필요하면 교환.
- 원소 수가 n인 배열에서 n - 1번 비교/교환을 하게 됨
- 이러한 일련의 과정을 패스라고 함(총 n-1번의 패스를 수행해야 함)
- 첫 번째 패스가 끝나면 n-2번 비교/교환을 함(두번 째 패스)
- 반복
from typing import MutableSequence
def bubble_sort(a: MutableSequence) -> None:
"""버블 정렬"""
n = len(a)
for i in range(n - 1):
for j in range(n - 1, i, -1):
if a[j - 1] > a[j]:
a[j - 1], a[j] = a[j], a[j - 1]
- 원소를 비교하는 횟수
(n - 1) + (n - 2) + ... + 1 = n(n-1) / 2- 실제 교환하는 횟수는 원솟값에 영향을 받음으로 위 도출결과의 절반인 n(n-1) / 4임
def bubble_sort(a: MutableSequence) -> None:
"""버블 정렬(교환 횟수에 따른 중단)"""
n = len(a)
for i in range(n - 1):
exchng = 0 # 패스에서 교환 횟수
for j in range(n - 1, i, -1):
if a[j - 1] > a[j]:
a[j - 1], a[j] = a[j], a[j - 1]
exchng += 1
if exchng == 0:
break
def bubble_sort(a: MutableSequence) -> None:
"""버블 정렬(스캔 범위를 제한)"""
n = len(a)
k = 0
while k < n - 1:
last = n - 1
for j in range(n - 1, k, -1):
if a[j - 1] > a[j]:
a[j - 1], a[j] = a[j], a[j - 1]
last = j
k = last
def shaker_sort(a: MutableSequence) -> None:
"""셰이커 정렬"""
left = 0
right = len(a) - 1
last = right
while left < right:
for j in range(right, left, -1):
if a[j - 1] > a[j]:
a[j - 1], a[j] = a[j], a[j - 1]
last = j
left = last
for j in range(left, right):
if a[j] > a[j + 1]:
a[j], a[j + 1] = a[j + 1], a[j]
last = j
right = last
- 아직 정렬하지 않은 부분에서 값이 가장 작은 원소를 선택
- 아직 정렬하지 않은 부분에서 맨 앞에 있는 원소를 교환
def selection_sort(a: MutableSequence) -> None:
"""단순 선택 정렬"""
n = len(a)
for i in range(n - 1):
min = i # 정렬 할 부분에서 가장 작은 원소의 인덱스
for j in range(i + 1, n):
if a[j] < a[min]:
min = j
a[i], a[min] = a[min], a[i] # 정렬 할 부분에서 맨 앞의 원소와 가장 작은 원소를 교환
- 두번째 원소를 첫번째 원소와 비교 후 정렬
- 세번째 원소를 앞쪽 정렬 완료된 부분과 비교해 알맞은 위치에 삽입
- 반복
def insertion_sort(a: MutableSequence) -> None:
"""단순 삽입 정렬"""
n = len(a)
for i in range(1, n):
j = i
tmp = a[i]
while j > 0 and a[j - 1] > tmp:
a[j] = a[j - 1]
j -= 1
a[j] = tmp
def shell_sort(a: MutableSequence) -> None:
"""셸 정렬"""
n = len(a)
h = n // 2
while h > 0:
for i in range(h, n):
j = i - h
tmp = a[i]
while j >= 0 and a[j] > tmp:
a[j + h] = a[j]
j -= h
a[j + h] = tmp
h //= 2
가운데를 피벗(x)으로 놓고, 왼쪽 끝 원소를 pl, 오른쪽 끝 원소를 pr으로 둠
def partition(a: MutableSequence) -> None:
"""배열을 분할하여 출력"""
n = len(a)
pl = 0 # 왼쪽 커서
pr = n - 1 # 오른쪽 커서
x = a[n // 2] # 피벗(가운데 원소)
while pl <= pr:
while a[pl] < x: pl += 1
while a[pr] > x: pr -= 1
if pl <= pr:
a[pl], a[pr] = a[pr], a[pl]
pl += 1
pr -= 1
"""a[left] ~ a[right]를 퀵 정렬"""
pl = left # 왼쪽 커서
pr = right # 오른쪽 커서
x = a[(left + right) // 2] # 피벗(가운데 요소)
while pl <= pr: # 실습 6-10과 같은 while 문
while a[pl] < x: pl += 1
while a[pr] > x: pr -= 1
if pl <= pr:
a[pl], a[pr] = a[pr], a[pl]
pl += 1
pr -= 1
if left < pr: qsort(a, left, pr)
if pl < right: qsort(a, pl, right)
def quick_sort(a: MutableSequence) -> None:
"""퀵 정렬"""
qsort(a, 0, len(a) - 1)