1. 0번째 원소와 1번째 원소를 비교 후 정렬
2. 1번째 원소와 2번째 원소를 비교 후 정렬
...
3. n-1번째 원소와 n번째 원소를 비교 후 정렬(1회 사이클)
4. 0번째 원소와 1번째 원소를 비교 후 정렬
5. 1번째 원소와 2번째 원소를 비교 후 정렬
6. n-2번째 원소와 n-1번째 원소를 비교 후 정렬(2회 사이클)
...
7. 0번째 원소와 1번째 원소를 비교 후 정렬
def BubbleSort(arr):
length = len(arr) - 1 # j에서 j + 1까지 비교하므로 마지막 숫자 비교 후 반복을 중단시키기 위해 len(arr) - 1 해준다
for i in range(length): # i 한턴 당 마지막 수가 정렬된다
swap = 0 # swap의 진행 여부를 판별하기 위한 변수 swap
for j in range(length - i):
if arr[j] > arr[j + 1]:
arr[j], arr[j + 1] = arr[j + 1], arr[j]
swap = 1
if swap == 0: # 진행 중 어느 턴에서 swap이 진행되지 않았다면 정렬이 완료가 된 것이므로 for문을 빠져나감
break
return arr
array = [1,7,5,21,13,35,18]
print(BubbleSort(array))
length = len(arr) - 1
swap
변수는 굳이 필요없으나 j번째 돌 때 swap이 진행되지 않으면 정렬이 완료된 것이므로 break로 빠져나오면 반복을 줄일 수 있다.1. 0번째 원소 ~ n번째 원소 중 가장 작은 값을 찾아 0번째 원소와 swap
2. 1번째 원소 ~ n번째 원소 중 가장 작은 값을 찾아 1번째 원소와 swap
...
3. n-1번째 원소 ~ n번째 원소 중 가장 작은 값을 찾아 n-1번째 원소와 swap
def SelectionSort(arr):
length = len(arr)
for i in range(length - 1): # n-1을 기준으로 검사 후에 정렬이 종료되므로 length - 1
min_index = i
for j in range(i, length): # i번 원소부터 마지막 원소 중에 가장 작은 값의 위치를 min_index에 저장하고 i번 원소와 자리 바꾸기
if arr[j] < arr[min_index]:
min_index = j
arr[i], arr[min_index] = arr[min_index], arr[i]
array = [1,7,5,21,13,35,18]
SelectionSort(array)
print(array)
min_index
에 저장하고 모든 값의 검사가 끝나면 i번 원소와 swap1. 0번 원소를 건너뛴다
2. 0~1번 원소 중 1번 원소가 들어가야 할 위치를 찾아서 넣는다
3. 0~2번 원소 중 2번 원소가 들어가야 할 위치를 찾아서 넣는다
4. 0~3번 원소 중 3번 원소가 들어가야 할 위치를 찾아서 넣는다
...
5. 0~n번 원소 중 n번 원소가 들어가야 할 위치를 찾아서 넣는다
def InsertionSort(arr):
length = len(arr)
for i in range(1, length): # 0번 원소는 건너 뛴다
j = i
while j > 0 and arr[j - 1] > arr[j]: # 기본 범위에 추가된 i번째 원소가 그 전 원소 보다 작다면 반복해서 swap
arr[j - 1], arr[j] = arr[j], arr[j - 1]
j -= 1
array = [1,7,5,21,13,35,18]
InsertionSort(array)
print(array)
1. [1, 0, 7, 4] 리스트를 받는다
2. 각 리스트의 길이가 1이 될 때까지 반으로 나눈다 ( [1], [0], [7], [4] )
3. 왼쪽의 0번 원소( [1] )와 오른쪽의 0번 원소( [0] ) 중 작은 값을 먼저 넣은 새로운 리스트를 생성한다 ( [0 , 1] )
4. 왼쪽의 0번 원소( [7] )와 오른쪽의 0번 원소( [4] ) 중 작은 값을 먼저 넣은 새로운 리스트를 생성한다 ( [4, 7] )
5. 왼쪽의 0번 원소( [0] )와 오른쪽의 0번 원소( [4] ) 중 작은 값을 먼저 넣은 새로운 리스트를 생성한다 ( [0, ] )
6. 왼쪽의 0번 원소( [1] )와 오른쪽의 0번 원소( [4] ) 중 작은 값을 새로운 리스트에 병합한다 ( [0, 1, ] )
7. 값이 남았으므로 나머지 값을 병합해준다 ( [0, 1, 4, 7] )
def MergeSort_sort(arr):
if len(arr) < 2: # arr의 길이가 1이면 arr값을 그대로 리턴
return arr
mid = len(arr) // 2
left = MergeSort_sort(arr[:mid])
right = MergeSort_sort(arr[mid:])
return MergeSort_merge(left, right)
def MergeSort_merge(left, right):
i, j = 0, 0
new_list = []
while (i < len(left)) and (j < len(right)): # 왼쪽과 오른쪽 원소 0번 원소 중 작은 값을 먼저 넣은 새로운 리스트를 생성
if left[i] > right[j]:
new_list.append(right[j])
j += 1
else:
new_list.append(left[i])
i += 1
if i == len(left): # 위 while문에서 left든 right든 한쪽 값을 다 사용했다면 나머지 값을 전부 병합
new_list = new_list + right[j:]
elif j == len(right):
new_list = new_list + left[i:]
return new_list
array = [1,7,5,21,13,35,18]
print(MergeSort_sort(array))
1. 입력된 자료에서 하나의 원소를 고르고 피벗이라고 부르기로 한다(코드에선 마지막 값으로 정함)
2. 피벗을 기준으로 왼쪽에는 피벗보다 작은 값을, 오른쪽에는 피벗보다 큰 값으로 옮겨준다
3. i = unknown(다음 검사할 값),
b = big_value(피벗보다 큰 수),
p = 피벗(end),
start = small_value(피벗보다 작은 수)
이라고 할 때,
처음에는 i, b = start = 0이다
4. 이제 i가 오른쪽으로 한칸씩 움직이면서 검사하는데, 조건에 따라 나누면
list[i] < list[p]인 경우 i값과 b값을 swap하고 i와 b를 +1해준다
list[i] >= list[p]인 경우 i를 +1해준다
i가 p가 되면
list[p]와 list[b]를 swap하고 다음 divide를 귀해서 p의 위치를 리턴한다
def swap_elements(my_list, index1, index2):
"""index1과 index2를 swap하는 함수"""
my_list[index1], my_list[index2] = my_list[index2], my_list[index1]
return my_list
def partition(my_list, start, end):
"""my_list start~end까지 정렬하는 함수"""
p = end
b = start
i = start
while i < len(my_list):
if my_list[i] > my_list[p]:
i += 1
elif my_list[i] < my_list[p]:
swap_elements(my_list, i, b)
b += 1
i += 1
else:
i += 1
swap_elements(my_list, b, p)
p = b
return p
def quicksort(my_list, start, end):
"""재귀함수"""
# base case
if end - start < 1:
return
else:
p = partition(my_list, start, end)
quicksort(my_list, start, p-1)
quicksort(my_list, p+1, end)
return
array = [1,7,5,21,13,35,18]
quicksort(array, 0, len(array) - 1)
print(array)
swap_elements
는 두 인덱스 값을 바꿔주는 서브함수partition
은 위의 설명에 따라 i값을 한칸씩 움직이면서 p값을 기준으로 왼쪽과 오른쪽으로 값을 나누는 함수quicksort
는 end == start
가 되는 base case를 구분해주고 partition
의 return인 p
를 이용해 나눠서 재귀를 하는 함수-알고리즘 진행 순서
1. 가장 작은 데이터부터 가장 큰 데이터까지 모두 담길 수 있는 길이의 리스트를 생성한다(카운트 리스트)
2. 정렬하고자 하는 데이터를 하나씩 확인하며 카운트 리스트 인덱스에 해당하는 value를 +1해준다
3. 카운트 리스트에서 0인 값을 제외하고 하나씩 출력해준다
4. 출력할 때 카운트 리스트를 누적합한 리스트로 만들어 인덱스의 위치를 표현해 줄 수 있다
array = [1,7,5,21,13,35,18]
count_list = [0] * (max(array) + 1)
for i in array: # 카운트 리스트의 인덱스에 해당하는 값 +1씩 카운트
count_list[i] += 1
for j in range(1, len(count_list)): # 카운트 리스트를 누적합으로 만듦
count_list[j] += count_list[j-1]
new_array = [0] * (len(array)) # 정렬된 리스트를 담을 리스트 선언
for k in array: # 기존 배열의 값을 누적합 카운트 리스트의 인덱스에서 찾는다
new_array[count_list[k] - 1] = k
count_list[k] -= 1
print(new_array)