공부/알고리즘 (c++)
퀵 정렬 (Quick Sort)
원클릭쓰리버그
2022. 3. 16. 18:57
728x90
퀵 정렬(Quicksort)은 찰스 앤터니 리처드 호어가 개발한 정렬 알고리즘이다.
다른 원소와의 비교만으로 정렬을 수행하는 비교 정렬에 속한다.
퀵 정렬은 n개의 데이터를 정렬할 때, 최악의 경우에는 O(n2)번의 비교를 수행하고, 평균적으로 O(n log n)번의 비교를 수행한다.
알고리즘
퀵 정렬은 분할 정복(divide and conquer) 방법을 통해 리스트를 정렬한다.
- 리스트 가운데서 하나의 원소를 고른다. 이렇게 고른 원소를 피벗이라고 한다.
- 피벗 앞에는 피벗보다 값이 작은 모든 원소들이 오고, 피벗 뒤에는 피벗보다 값이 큰 모든 원소들이 오도록 피벗을 기준으로 리스트를 둘로 나눈다. 이렇게 리스트를 둘로 나누는 것을 분할이라고 한다. 분할을 마친 뒤에 피벗은 더 이상 움직이지 않는다.
- 분할된 두 개의 작은 리스트에 대해 재귀(Recursion)적으로 이 과정을 반복한다. 재귀는 리스트의 크기가 0이나 1이 될 때까지 반복된다.
재귀 호출이 한번 진행될 때마다 최소한 하나의 원소는 최종적으로 위치가 정해지므로, 이 알고리즘은 반드시 끝난다는 것을 보장할 수 있다.
단계
1) low값과 high값 지정
- pivot >= arr[low]일 동안 low를 오른쪽으로 이동
- pivot <= arr[high]일 동안 high를 왼쪽으로 이동
2) 비교하기
- low < high라면, arr[low]와 arr[high] 데이터 교체
3) 피벗 교체하기
- pivot의 값과 high의 데이터를 교체한다.
4) 피벗과 high 데이터를 교환한 지점을 기준으로 분할하여 재귀적으로 다시 반복 실행
#include <iostream>
#include <vector>
#include <queue>
#include <stack>
#include <list>
using namespace std;
#include <thread>
// 퀵 정렬
// Quick Sort
// [5][1][3][7][9][2][4][6][8]
int Partition(vector<int>& v, int left, int right)
{
int pivot = v[left]; //5
int low = left + 1; //1
int high = right; //8
while (low <= high)
{
while (low <= right && pivot >= v[low])
low++;
while (high >= left + 1 && pivot <= v[high])
high--;
if (low < high)
swap(v[low], v[high]);
}
swap(v[left], v[high]);
return high;
}
// O(N^2) => 최악의 경우.
// O(NlogN) => 평균적인 경우.
void QuickSort(vector<int>& v, int left, int right)
{
if (left > right)
return;
int pivot = Partition(v, left, right);
QuickSort(v, left, pivot - 1);
QuickSort(v, pivot + 1, right);
}
int main()
{
vector<int> v;
srand(time(0));
for (int i = 0; i < 50; i++)
{
int randValue = rand() % 100;
v.push_back(randValue);
}
QuickSort(v, 0, v.size()-1);
}