강의노트 16.[정렬] - bubble sort(버블정렬), insertion sort(삽입정렬), selection sort(선택정렬)

|

패스트캠퍼스 컴퓨터공학 입문 수업을 듣고 중요한 내용을 정리했습니다. 개인공부 후 자료를 남기기 위한 목적임으로 내용 상에 오류가 있을 수 있습니다.

O(n^2)의 성능을 가진 버블정렬, 삽입정렬, 선택정렬에 대해서 알아본다.

bubble sort (버블정렬)

구현 1 (버블정렬)

def BubbleSort(li):
    list_length = len(li)

    #length가 4라면
    #바깥 루프는 3번 돌아야 하므로
    #range()는 0, 1, 2까지 즉 range(3)이 되야 하므로
    #range(list_length-1)이 되어야 한다.
    for i in range(list_length-1):
        #안쪽 루프는 1번당 3-> 2-> 1
        #즉 range(4 - 0 - 1) ->
        #range(4 - 1 - 1) ->
        #range(4 - 2 - 1)
        #range(list_leng - i - 1)
        for j in range(list_length-i-1):
            #만약 앞에 있는 값이 크다면 두 개를 교환
            if li[j] > li[j+1]:
                li[j], li[j+1] = li[j+1], li[j]


if __name__ == "__main__":
    li = [2, 3, 1, 4]
    BubbleSort(li)
    print(li)
def bubble_sort(li):
    length = len(li) - 1
    for i in range(length):
        for j in range(length-i):
            if li[j] > li[j+1]:
                li[j], li[j+1] = li[j+1], li[j]

if __name__ == "__main__":
    li = [10,2,3,4,1,7,0]
    bubble_sort(li)
    print(li)

구현 2 (버블정렬)

  • 구현 1 보다 불필요한 반복이 추가된다. (이미 정렬된 부분에 대한 비교)
import unittest

def bubblesort(alist):
    for i in range(len(alist)-1):
        for j in range(len(alist)-1):
            if alist[j] > alist[j+1]:
                alist[j], alist[j+1] = alist[j+1], alist[j]
    return alist


class unit_test(unittest.TestCase):
    def test(self):
        self.assertEqual([1,2,3,4,5,6], bubblesort([4,6,1,3,5,2]))

if __name__=='__main__':
    unittest.main()

selection sort(선택정렬)

  • 최소값을 선택하는 과정을 반복해서 선택 정렬이라 부른다고 한다.
  • 위키백과
    1. 주어진 리스트 중에 최솟값을 찾는다
    2. 그 값을 맨 앞에 위치한 값과 교체한다(패스(pass))
    3. 맨 처음 위치를 뺀 나머지 리스트를 같은 방법으로 교체한다.

구현 1 (선택정렬)

#맨 왼쪽부터 하나씩 최소값을 선택(selection)해 채운다

def selection_sort(li):
    for i in range(len(li)-1):
        min_idx = i
        for j in range(i+1, len(li)):
            if li[min_idx] > li[j]:
                min_idx = j
        if min_idx != i:
            li[i], li[min_idx] = li[min_idx], li[i]
    return li

if __name__ == "__main__":
    li = [4, 6, 1, 7, 2, 8, 3, 5, 9, 10, 12, 11]
    SelectionSort(li)
    print(li)

구현 2 (선택정렬)

  • 구현 1의 방식이 더 일반적이다.
def selection_sort(li):
    for i in range(len(li)-1):
        for j in range(i+1, len(li)):
            if li[i] > li[j]:
                li[i], li[j] = li[j], li[i]
    return li

if __name__ == "__main__":
	li = [4, 6, 1, 7, 2, 8, 3, 5, 9, 10, 12, 11]
	selection_sort(li)
	print(li)

구현 3 (선택정렬)

  • unittest 를 활용한다.
# 풀이 3

import unittest

def selection_sort(li):
    for i in range(len(li)-1):
        min_idx = i
        for j in range(i+1, len(li)):
            if li[min_idx] > li[j]:
                min_idx = j
        li[i], li[min_idx] = li[min_idx], li[i]
    return li

class unit_test(unittest.TestCase):
    def test(self):
        self.assertEqual([1, 2, 3, 4, 5, 6], selection_sort([4, 6, 1, 3, 5, 2]))
        self.assertEqual([1, 2, 3, 4, 5, 6], selection_sort([6, 4, 3, 1, 2, 5]))
        self.assertEqual([1, 2, 3, 4, 5, 6], selection_sort([6, 5, 4, 3, 2, 1]))

if __name__ == '__main__':
    unittest.main()


#----------------------------------------------------------------------
# Ran 1 test in 0.000s
# OK

insertion sort(삽입정렬)

  • 작은 원소를 골라 앞쪽부터 정렬
  • 자료 배열의 모든 요소를 앞에서부터 차례대로 이미 정렬된 배열 부분과 비교하여, 자신의 위치를 찾아 삽입함으로써 정렬을 완성하는 알고리즘
  • 최악의 경우 O(n^2)의 시간복잡도를 가진다.
  • 하지만 안쪽 루프에 군더더기가 없기 때문에 삽입 정렬을 입력 크기가 작을 때는 빠른 내부 정렬 알고리즘이다.

31 25 12 22 11 처음 상태

31 [25] 12 22 11 두 번째 원소를 부분 리스트에서 적절한 위치에 삽입한다.

<25> 31 [12] 22 11 세 번째 원소를 부분 리스트에서 적절한 위치에 삽입한다.

<12> 25 31 [22] 11 네 번째 원소를 부분 리스트에서 적절한 위치에 삽입한다.

12 <22> 25 31 [11] 마지막 원소를 부분 리스트에서 적절한 위치에 삽입한다.

<11> 12 22 25 31 종료.

구현 1(삽입정렬)

def insertion_sort(li):
    for i in range(1, len(li)):
        j = i - 1
        key = li[i]
        while li[j] > key and j >= 0:
            li[j+1] = li[j]
            j = j -1
        li[j+1] = key
    return li

if __name__ == "__main__":
	li = [4, 6, 1, 7, 2, 8, 3, 5, 9, 10, 12, 11]
	insertion_sort(li)

구현 2(삽입정렬)

#이미 정렬되어 있는 배열에 데이터를 삽입(insertion)한다고 하여 InsertionSort
def InsertionSort(li):
    list_length = len(li)

    for i in range(1, list_length):
        unsortedData = li[i]
        properIdx = 0

        for j in range(i-1, -1, -1):
            if li[j] > unsortedData:
                li[j+1] = li[j]
            else:
                properIdx = j+1
                break

        li[properIdx] = unsortedData

if __name__ == "__main__":
    li = [2, 5, 7, 3, 6, 1, 4, 8]
    InsertionSort(li)
    print(li)