정렬
선택 정렬
가장 작은 것부터 꺼내 놓기
카드 여섯 장을 작은 수부터 왼쪽에 늘어놓아 보세요. 한 장씩 보며 가장 작은 카드를 찾아 왼쪽 끝으로 보냅니다.
카드 여섯 장을 작은 수부터 왼쪽에 늘어놓습니다. 먼저 맞혀 보세요. 첫 바퀴를 끝내면 맨 앞에 어떤 카드가 올까요?
5
2
9
1
7
4
견줘 본 횟수 0 · 바꾼 횟수 0
카드를 정렬하는 데 0번 견주고 0번 바꿨습니다.
5 → 2 → 1첫 바퀴에서 가장 작은 카드 후보가 이렇게 바뀌었습니다.
버블 정렬 · 바꾼 횟수8번
선택 정렬 · 바꾼 횟수2번
한 바퀴에 가장 작은 카드 하나를 골라 맨 앞 빈 칸과 맞바꾸는 방법 = 선택 정렬
이미 정렬돼 있어도 훑는 횟수는 같다
- 바퀴마다 — 남은 카드를 끝까지 봐야 가장 작은 카드를 안다. 앞에서 찾아도 끝까지 본다
- 훑는 횟수 — 5 + 4 + 3 + 2 + 1 = 15번. 카드가 n장이면 n(n−1)/2번이다
- 정렬된 카드도 — 맨 앞이 가장 작은지 끝까지 봐야 안다. 위의 「이미 정렬된 카드로 해 보기」로 세어 보면 여전히 15번이다
코드는 후보 하나를 들고 훑는 것이 전부다
다음을 눌러 한 줄씩 넘기며 후보가 바뀌는 걸 보세요. 앞에서부터 확정된 칸이 쌓입니다.
50
21
92
13
74
45
다음을 눌러 한 줄씩 넘겨 보세요
n = 6
selection_sort.py
- 1def selection_sort(arr):
- 2 n = len(arr)
- 3 for i in range(n - 1):
- 4 min_idx = i
- 5 for j in range(i + 1, n):
- 6 if arr[j] < arr[min_idx]:
- 7 min_idx = j
- 8 arr[i], arr[min_idx] = arr[min_idx], arr[i]
- 9 return arr
0 / 37
i— 지금 채우는 칸. 앞 i칸은 이미 자리를 잡았다min_idx— 지금까지 본 카드 중 가장 작은 카드의 칸 번호(후보)j— 지금 견주는 칸.i + 1부터 끝까지 간다
거꾸로 선 카드 6 5 4 3 2 1 을 선택 정렬하면 자리를 몇 번 바꿀까요?
선택 정렬에서 틀리는 자리
- 같은 값의 순서가 뒤집힌다 — 먼 칸과 맞바꾼다.
2a 2b 1c를 정렬하면 1c 2b 2a 가 된다. 안정 정렬이 아니다 <대신<=— 같은 값 중 뒤쪽을 후보로 잡는다. 이미 정렬된1a 1b 2c가 1b 1a 2c 로 바뀐다range(i + 1, n)대신range(i, n)— 자기 자신과도 견줘 비교가 15번에서 20번으로 는다. 답은 그대로 맞다
쓸 일은 적지만 이럴 때 나온다
n 이 작다바꾸는(쓰는) 횟수를 줄여야 한다k 번째로 작은 것까지만 필요하다
실전에서 정렬이 필요할 때는 sorted() 한 줄이면 됩니다.
다음 장에서는 카드를 한 장씩 알맞은 자리에 끼워 넣는 삽입 정렬을 봅니다.