빠른 정렬

Harshit Jindal 2023년10월12일
  1. 빠른 정렬 알고리즘
  2. 빠른 정렬 예
  3. 빠른 정렬 알고리즘 구현
  4. 빠른 정렬 알고리즘 복잡성
빠른 정렬

빠른 정렬은 분할 및 정복 알고리즘의 원리를 기반으로하는 매우 효율적인 정렬 알고리즘입니다. 빠른 정렬은 선택한 피벗 요소를 중심으로 배열을 두 부분으로 분할하여 작동합니다. 작은 요소는 피벗의 왼쪽으로 이동하고 큰 요소는 오른쪽으로 이동합니다. 그런 다음 왼쪽 및 오른쪽 하위 부분이 재귀 적으로 정렬되어 전체 배열을 정렬합니다. 일반적인 정렬 알고리즘보다 약 2또는 3배 빠르기 때문에 빠른 정렬이라고합니다. 빠른 정렬은 데이터 구조 내부의 정보 검색 및 수치 계산에 널리 사용됩니다.

빠른 정렬 알고리즘

n 요소를 포함하는 정렬되지 않은 배열A[]가 있다고 가정 해 보겠습니다. 두 개의 변수begend를 취한 다음 시작 및 끝 요소의 색인을 저장합니다.

파티션()

  • 피벗 요소로 마지막 요소 (구현에 따라 임의 일 수 있음)를 선택합니다.
  • 포인터 i의 값을 ‘beg-1’로 초기화하여 피벗보다 작은 요소를 배열의 시작으로 이동할 수 있도록합니다.
  • 배열을 반복적으로 탐색하고 각 요소에 대해 다음을 수행합니다.
  • 요소A[i]<pivoti를 증가시키고A[i]A[j]로 바꿉니다.
  • A[i]를 ‘A[end]‘로 바꾸어 피벗 요소를 올바른 위치에 놓습니다.
  • 피벗 요소의 인덱스를 반환합니다.

QuickSort()

  • 피벗 인덱스 pi를 선택합니다.
  • 피벗 인덱스를 중심으로 배열을 분할합니다.
  • 피벗 요소의 왼쪽arr[beg, ..., pi]에서 요소를 재귀 적으로 정렬합니다.
  • 피벗 요소의 오른쪽arr[pi + 1, ..., end]에서 요소를 재귀 적으로 정렬합니다.

빠른 정렬 알고리즘

빠른 정렬 알고리즘 결과

빠른 정렬 예

배열이(6,5,1,4,2,3)이라고 가정합니다. 빠른 정렬 알고리즘을 사용하여 정렬합니다.

  • 첫 번째3이 피벗 요소로 선택되고 배열은 두 개의 하위 부분(1,2)-작은 요소 및(6,5,4)-큰 요소로 분할됩니다. 그리고3이 정렬 된 위치에 놓입니다. 형성된 두 개의 하위 배열은 재귀 적으로 정렬됩니다.
  • 하위 배열의 경우 (1,2)의 경우,2가 pivot 요소로 선택되고 올바른 위치에 놓이고 이미 정렬 된 subarray(1)이 형성됩니다.
  • 하위 배열의 경우 (6,5,4)의 경우4가 정렬 된 위치에 놓이고 하위 배열의 경우 (6,5)가 생성 된 후 재귀 적으로 정렬됩니다.
  • 하위 배열(6,5)의 경우5를 피벗으로 선택하고 올바른 위치에 놓으면(6)이 새 하위 배열로 제공됩니다. 단일 요소 하위 배열(6)이 이미 정렬되었습니다.
  • 마지막으로 정렬 된 배열을(1, 2, 3, 4, 5, 6)로 얻습니다.

빠른 정렬 알고리즘 구현

#include <bits/stdc++.h>
using namespace std;

int partition(int arr[], int beg, int end) {
  // Select the last element as pivot element
  int pivot = arr[end];
  int i = (beg - 1);
  // Move smaller elements to left side and larger on right side
  for (int j = beg; j < end; j++) {
    if (arr[j] <= pivot) {
      i++;
      swap(arr[i], arr[j]);
    }
  }
  swap(arr[i + 1],
       arr[end]);  // Move pivot element to its right position in array
  return (i + 1);
}

void quickSort(int arr[], int beg, int end) {
  if (beg < end) {
    int pi = partition(arr, beg, end);
    quickSort(arr, beg,
              pi - 1);  // Recursive Sort element on left side of partition
    quickSort(arr, pi + 1,
              end);  // Recursive Sort element on right side of partition
  }
}
int main() {
  int n = 6;
  int arr[6] = {5, 3, 4, 2, 1, 6};
  cout << "Input array: ";
  for (int i = 0; i < n; i++) {
    cout << arr[i] << " ";
  }
  cout << "\n";
  quickSort(arr, 0, n - 1);  // Sort elements in ascending order
  cout << "Output array: ";
  for (int i = 0; i < n; i++) {
    cout << arr[i] << " ";
  }
  cout << "\n";
}

빠른 정렬 알고리즘 복잡성

시간 복잡성

  • 평균 사례

빠른 정렬에 걸리는 시간은 다음과 같은 반복 관계로 지정됩니다.

 T(n) = T(k) + T(n-k-1) + θ(n)

여기서 k는 피벗 요소보다 작거나 큰 요소의 수를 나타냅니다.

이 반복 관계의 결과는T(n) = nLogn을 제공합니다. 평균 케이스는 무작위로 균형이 맞지 않는 파티션을 얻을 때 발생합니다. 시간 복잡도는 [Big Theta] :O(nLogn)의 순서입니다.

  • 최악의 경우
T(n) = T(n-1) + θ(n)

최악의 경우는 피벗 요소가 항상 배열의 가장 큰 요소이거나 가장 작은 요소 일 때 발생합니다. 이 경우 모든 요소가 하나의 하위 배열에 속하고 최대 n호출이 이루어져야합니다. 최악의 경우 시간 복잡도는 [Big O] : O(n2)입니다.

  • 베스트 케이스
 T(n) = 2T(n/2) + θ(n)

가장 좋은 경우는 선택한 피벗 요소가 항상 중간 요소이거나 두 파티션이 균등하게 균형을 이루는 경우 (예 : 크기 차이가 1이하인 경우)입니다. 최적의 시간 복잡도는 [Big Omega] :O(nLogn)입니다.

공간 복잡성

빠른 정렬 알고리즘의 평균 케이스 공간 복잡도는 O(Logn)입니다. 재귀 스택에 필요한 공간입니다. 그러나 배열을 정렬하는 데 n재귀가 필요한 최악의 경우 공간 복잡성은 O(n)입니다.

Harshit Jindal avatar Harshit Jindal avatar

Harshit Jindal has done his Bachelors in Computer Science Engineering(2021) from DTU. He has always been a problem solver and now turned that into his profession. Currently working at M365 Cloud Security team(Torus) on Cloud Security Services and Datacenter Buildout Automation.

LinkedIn

관련 문장 - Sort Algorithm