공부/알고리즘 (c++)

퀵 정렬 (Quick Sort)

원클릭쓰리버그 2022. 3. 16. 18:57
728x90

퀵 정렬(Quicksort)은 찰스 앤터니 리처드 호어가 개발한 정렬 알고리즘이다.

다른 원소와의 비교만으로 정렬을 수행하는 비교 정렬에 속한다.

퀵 정렬은 n개의 데이터를 정렬할 때, 최악의 경우에는 O(n2)번의 비교를 수행하고, 평균적으로 O(n log n)번의 비교를 수행한다.

 

알고리즘

퀵 정렬은 분할 정복(divide and conquer) 방법을 통해 리스트를 정렬한다.

  1. 리스트 가운데서 하나의 원소를 고른다. 이렇게 고른 원소를 피벗이라고 한다.
  2. 피벗 앞에는 피벗보다 값이 작은 모든 원소들이 오고, 피벗 뒤에는 피벗보다 값이 큰 모든 원소들이 오도록 피벗을 기준으로 리스트를 둘로 나눈다. 이렇게 리스트를 둘로 나누는 것을 분할이라고 한다. 분할을 마친 뒤에 피벗은 더 이상 움직이지 않는다.
  3. 분할된 두 개의 작은 리스트에 대해 재귀(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);

}