ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 정렬
    Algorithms in Python/notes 2021. 1. 20. 14:51

     

    정렬 (Sorting)

    데이터를 특정한 기준에 따라 순서대로 나열하는 것을 말한다.

     


    선택 정렬(Selection Sort)

    정렬된 왼쪽 리스트와 정렬 안된 오른쪽 리스트를 가정하고, 오른쪽 리스트에서 최소값을 선택하여 오른쪽 리스트의 첫번째 수와 교환한다.

     

    • 선택 정렬의 소스코드

    arr = [7, 5, 9, 0, 3, 1, 6, 2, 4, 8]
    
    for i in range(len(arr)):
        min_index = i # 가장 작은 원소의 인덱스
        for j in range(i + 1, len(arr)):
            if arr[min_index] > arr[j]:
                min_index = j
        arr[i], arr[min_index] = arr[min_index], arr[i] # 교환
    
    print(arr)

     

    • 선택 정렬의 시간 복잡도

    (n -1) + (n - 2) + ... + 2 = n(n - 1) / 2 = O(n2)

     


    삽입 정렬(Insertion Sort)

    정렬된 왼쪽 리스트와 정렬 안된 오른쪽 리스트를 가정하고, 오른쪽 리스트의 첫번째 값을 선택하여 정렬된 왼쪽 리스트에 적절한 위치를 찾아 삽입한다.

    * 상대적 위치가 바뀌지 않음

     

    • 삽입 정렬의 소스코드

    arr = [7, 5, 9, 0, 3, 1, 6, 2, 4, 8]
    
    for i in range(1, len(arr)):
        for j in range(i, 0, -1):
            if arr[j] < arr[j - 1]: # 한 칸씩 왼쪽으로 이동
                arr[j], arr[j - 1] = arr[j - 1], arr[j]
            else:   # 자신보다 작은 데이터를 만나면 멈춘다.
                break
    
    print(arr)

     

    • 삽입 정렬의 시간복잡도

    - 최선의 경우(이미 정렬되어 있는 경우) : O(n)

    - 최악의 경우(역순으로 정렬되어 있는 경우) : O(n2)

     


    퀵 정렬(Quick Sort)

    pivot을 기준으로 기준보다 큰 데이터와 작은 데이터의 위치를 바꾸는 방법이다.

    - 리스트의 첫 번째 데이터를 pivot이라 정한다.

    - pivot을 기준으로 큰 데이터와 작은 데이터를 교환하고, 엇갈린 위치에서 작은 데이터와 피벗위치를 교환한다.

    - pivovt을 기준으로 왼쪽리스트와 오른쪽 리스트에서 각각 다시 정렬을 수행한다. 

     

    • 퀵 정렬의 소스코드

    arr = [7, 5, 9, 0, 3, 1, 6, 2, 4, 8]
    
    def quick_sort(arr):
        # 리스트가 하나 이하의 원소만을 담고 있다면 종료한다.
        if len(arr) <= 1:
            return arr
        
        pivot = arr[0]      # 피벗을 첫 번째 원소로 지정한다.
        tail = array[1:]    # 피벗을 제외한 리스트
        
        left_side = [x for x in tail if x <= pivot] # 분할된 왼쪽 부분
        right_side = [x for x in tail if x > pivot] # 분할된 오른쪽 부분
        
        # 분할 이후 왼쪽 부분과 오른쪽 부분에서 각각 정렬 수행, 전체 리스트를 반화
        return quick_sort(left_side) + [pivot] + quick_sort(right_side)
    
    print(quick_sort(arr))

     

    • 퀵 정렬의 시간복잡도

    - 최선의 경우(균등하게 분할 되는 경우) : O(nlogn)

    더보기

    T(n) = (n - 1) + 2*T(n / 2)

    T(1) = 0

    - 최악의 경우(불균등한 경우, 정렬된 리스트를 정렬하는 경우) : O(n2)

     


    계수 정렬(Count Sort)

    특정한 조건이 부합할 때만 사용할 수 있지만 매우 빠른 정렬 알고리즘이다. 데이터의 크기 범위가 제한되어 정수 형태로 표현할 수 있을 때만 사용할 수 있으며, 가장 큰 데이터와 가장 작은 데이터의 차이가 너무 크다면 계수 정렬은 사용할 수 없다. 계수 정렬을 이용할 때는 '모든 범위를 담을 수 있는 크기의 리스트를 선언'해야 하기 때문이다.

     

    정리하자면 데이터의 크기가 한정되어 있고 데이터가 많이 중복되어 있을 수록 유리하고 항상 사용할 수 없다.

    계수 정렬은 앞의 정렬과 다르게 직접 데이터 값을 비교하는 비교 기반의 정렬 알고리즘이 아니다.

     

    arr = [7, 5, 9, 0, 3, 1, 6, 2, 9, 1, 4, 8, 0, 5, 2]

    - count 리스트에 각 데이터가 몇 번 등장했는지 기록한다.'

    - count 리스트 첫 번째 데이터부터 차례때로 그 값만큼 인덱스를 출력한다.

     

    • 계수 정렬의 소스코드

    # 모든 원소의 값이 0보다 크거나 같다고 가정
    arr = [7, 5, 9, 0, 3, 1, 6, 2, 9, 1, 4, 8, 0, 5, 2]
    
    # 모든 범위를 포함하는 리스트 선언(모든 값은 0으로 초기화)
    count = [0] * (max(arr) + 1)
    
    for i in range(len(arr)):
        count[arr[i]] += 1  # 각 데이터에 해당하는 인덱스의 값 증가
    
    for i in range(len(count)): # 리스트에 기록된 정렬 정보 확인
        for j in range(count[i]):
            print(i, end=' ')

     

    • 계수 정렬의 시간복잡도

    데이터의 개수가 n, 데이터 중 최댓값이 k일 때, O(n + k)

     

    • 계수 정렬의 공간복잡도

    데이터의 개수가 n, 데이터 중 최댓값이 k일 때, O(n + k)

     

     

    * 이것이 코딩테스트다 with 파이썬 - 나동빈

    'Algorithms in Python > notes' 카테고리의 다른 글

    Union-Find 알고리즘  (0) 2021.02.07
    DFS / BFS  (0) 2021.01.29
    이진 탐색, bisect 라이브러리  (0) 2021.01.21
    파이썬의 정렬 라이브러리  (0) 2021.01.20
    다이나믹 프로그래밍  (0) 2021.01.13

    댓글

Designed by Tistory.