inblog logo
|
백엔드블로그-dohyeong
    자료구조

    [자료구조] 정렬 Sorting

    Aug 18, 2023
    [자료구조] 정렬 Sorting
    Contents
    버블 정렬버블 정렬의 성능삽입정렬삽입 정렬의 성능퀵 정렬구체적인 과정퀵 정렬 사용전 해결해야할 2가지 문제퀵 정렬의 성능 측정

    버블 정렬

    💡
    자료구조를 순회하면서 이웃한 요소들끼리 데이터를 교환하며 정렬을 수행한다.
    notion image

    버블 정렬의 성능

    notion image
    위의 식처럼 데이터가 30,000개나 되는 요소는 약 450,000,000회의 비교 연산을 거쳐야 한다.
    def bubblesort(data): for i in range(len(data) - 1): for j in range(len(data) - i - 1): if data[j] > data[j + 1]: data[j], data[j + 1] = data[j + 1], data[j]
     

    삽입정렬

    💡
    자료구조를 순차적으로 순회하면서 순서에 어긋나는 요소를 찾고, 그 요소를 올바른 위치에 다시 삽입해나가는 정렬 알고리즘이다.
    notion image

    삽입 정렬의 성능

    notion image
    삽입 정렬은 자료구조가 정렬되어 있다면 한번도 비교를 거치지 않는다
    • 비교를 거치지 않는 경우 (n-1)
    • 역으로 정렬되어 있는 경우 최악 n(n-1) /2
    두개의 평균이 (n^2 + n -2) / 2 회 정도
     
    삽입 정렬시 30000개의 데이터 일때 평균 비교 횟수로 계산한다면 225,007,499회 이다.
    def insertionSort(data): for i in range(1, len(data)): for j in range(i, 0, -1): if data[j - 1] > data[j]: data[j - 1], data[j] = data[j], data[j - 1]
     

    퀵 정렬

    💡
    동작 과정을 한마디로 요약하면 기준 요소 선정 및 분할의 반복

    구체적인 과정

    1. 기준 요소 선정 및 정렬대상 분류
      1. 자료구조에서 기준이 될 요소를 임의로 선정하고 기준요소(Pivot) 의 값보다 작은 값을 가진 요소는 기준 요소의 왼쪽으로, 큰 값을 가지는 요소는 오른쪽으로 옮긴다
    1. 정렬대상 분할
      1. 기준 요소 왼쪽에는 기준 요소보다 작은 요소 그룹, 오른쪽에는 큰 요소의 그룹이 생긴다. 여기서 왼쪽 그룹과 오른쪽 그룹을 분할하여 각 그룹에 대해 1단계에 해당하는 과정을 수행
    1. 반복
      1. 그룹의 크기가 1 이하여서 더이상 분할할 수 없을 때 까지 1단계, 2단계 과정을 반복하면 정렬이 완료된다.
      2.  

    퀵 정렬 사용전 해결해야할 2가지 문제

    • 배열을 사용할 경우 퀵 정렬의 분할 과정을 어떻게 효율적으로 처리할 것 인가?
      • 링크드 리스트에서는 노드 삽입이 간단하지만 배열 요소 사이에서는 새로운 요소를 삽입하려면 다른 요소를 이동해야 하는데 큰 오버헤드 발생
      • notion image
    • 반복되는 분할 과정을 어떻게 처리할 것인가?
      • 재귀를 이용
    def quick_sort(array, start, end): if start >= end: # 원소가 1개인 경우 종료 return pivot = start # 피벗은 첫 번째 원소 left = start + 1 right = end while(left <= right): # 피벗보다 큰 데이터를 찾을 때까지 반복 while(left <= end and array[left] <= array[pivot]): left += 1 # 피벗보다 작은 데이터를 찾을 때까지 반복 while(right > start and array[right] >= array[pivot]): right -= 1 if(left > right): # 엇갈렸다면 작은 데이터와 피벗을 교체 array[right], array[pivot] = array[pivot], array[right] else: # 엇갈리지 않았다면 작은 데이터와 큰 데이터를 교체 array[left], array[right] = array[right], array[left] # 분할 이후 왼쪽 부분과 오른쪽 부분에서 각각 정렬 수행 quick_sort(array, start, right - 1) quick_sort(array, right + 1, end) # 파이썬을 장점을 활용한 퀵정렬 def quickSort(array): if len(array) <= 1: return array pivot = array[0] tail = array[1:] leftSide = [x for x in tail if x <= pivot] rightSide = [x for x in tail if x > pivot] return quickSort(leftSide) + [pivot] + quickSort(rightSide)
     

    퀵 정렬의 성능 측정

    기준 요소 선정과 분할의 반복으로 동작한다.
    • 데이터가 무작위로 배치된 경우에 최고 성능을 자랑함
    notion image
    자료구조의 크기가 n일 때 퀵정렬의 재귀 호출의 깊이는 logN이다
    재귀 호출의 깊이 * 각 재귀 호출 단계에서의 비교 횟수
    N * logN = NlogN
     
    30000개를 비교할 때 446180 번만에 비교를 수행해서 정렬이 된다.
    • 최악의 경우
      • 재귀 호출마다 자료 구조 분할이 1 : n-1 로 이루어 지는 것
        notion image
        notion image
    💡
    퀵 정렬은 평균적으로 1.39nlogn회 비교를 수행한다. 최선의 경우 보다 39퍼 정도 느린 성능인 수치
    Share article
    Contents
    버블 정렬버블 정렬의 성능삽입정렬삽입 정렬의 성능퀵 정렬구체적인 과정퀵 정렬 사용전 해결해야할 2가지 문제퀵 정렬의 성능 측정

    백엔드블로그-dohyeong

    RSS·Powered by Inblog