강의내용 복습/컴퓨터 알고리즘

분할 정복 알고리즘 - Quick Sort

코오오 코오 2023. 4. 21. 11:31

 

-방법

1)배열의 원소 하나를 피봇(pivot)삼고 기준

2)피봇보다 작은 숫자들은 왼쪽, 피봇보다 큰 숫자들은 오른쪽에 위치하도록 분할

3)분할된 부분문제에 대해서도 위와 동일한 과정을 재귀적으로 수행하여 정렬

+이 때, 피봇은 분할된 왼편이나 오른편 부분에 포함되지 않는다. 

 

-Pseudo Code

QuickSort(A, left, right)
입력: 배열 A[left]~A[right]
출력: 정렬된 배열 A[left]~A[right]
1. if (left < right) {//배열 A의 가장 왼쪽 원소의 인덱스가 가장 오른쪽 원소의 인덱스보다 작으면, 정렬 수행. 그렇지 않으면 1개의 원소를 정렬하는 경우임. 
2. 피봇을 A[left]~A[right] 중에서 선택하고, 피봇을 A[left]와 자리를 바꾼 후, 피봇과 각 원소를 비교. 피봇보다 작은 숫자:A[left]~A[p-1] 피봇보다 큰 숫자:A[p+1]~A[right] 피봇: A[p]
3. QuickSort(A, left, p-1) // 피봇보다 작은 그룹
4. QuickSort(A, p+1 right) // 피봇보다 큰 그룹

 

-Time Complexity

퀵 정렬의 성능은 어떤 피봇을 선택하느냐에 따라 달라진다.

 

1.피봇으로 항상 가장 작은 숫자가 선택될 경우(worst)

->한 번에 숫자 하나씩만 정렬되고, recursion을 n번 해야한다.

->n-1 걸리는 비교가 n번 일어남 =>O(n^2)

 

2.중간의 값을 피봇으로 선정한 경우(best)

->한 번에 전체의 1/2이 정렬된다. recursion을 log2n번 해야한다.

->n-1 걸리는 비교가 log2n번 일어남 =>O(nlogn)

 

3.결론. 평균 경우 시간복잡도

->피봇을 항상 랜덤하게 선택한다고 가정하면, 평균으로 시간 복잡도를 계산한다.

=>O(nlogn)

 

-소스코드

#include <stdio.h>
#include <stdlib.h>
#define SIZE 12

void QuickSort(int* A, int left, int right) {
	if (left < right) {//배열의 원소의 수가 2개 이상이면
		int p, temp;

		p = (left + right) / 2 + 1;//피봇 선택. 중간 원소의 인덱스로 선택했다.
		temp = A[left];
		A[left] = A[p];
		A[p] = temp;//피봇을 A[left]와 자리를 바꾼다.

		//A[left]와 A[p+1]~A[right]를 비교한다.
		int i = left + 1;//배열의 원소를 하나씩 비교한다. i는 피봇보다 큰 값을 찾는다.
		int j = right;//j는 피봇보다 작은 값을 찾는다.

		while (i <= j) {//왼쪽과 오른쪽에서 시작한 i, j가 만나게 되면 비교 종료한다.
			while (A[i] <= A[left] && i <= right)//피봇보다 작은 값이면 넘어감
				i++;
			while (A[j] >= A[left] && j > left)//피봇보다 큰 값이면 넘어감
				j--;
			if (i > j) {//i와 j가 엇갈리면 피봇 알맞은 위치로 바꿔줌
				temp = A[j];
				A[j] = A[left];
				A[left] = temp;
			}
			else {//i번째 값과 j번째 값의 자리를 바꾼다.
				temp = A[j];
				A[j] = A[i];
				A[i] = temp;
			}
			for (int i = 0; i < SIZE; i++) {
				printf(" %d  ", A[i]);
			}
			printf("\n");
		}
		QuickSort(A, left, j - 1);//피봇보다 작은 그룹
		QuickSort(A, j + 1, right);//피봇보다 큰 그룹
	}
}

int main() {
	int n = SIZE;
	int a[] = { 6,3,11,9,12,2,8,15,18,10,7,14 };

	printf("Before Sorting:");
	for (int i = 0; i < SIZE; i++) {
		printf(" %d  ", a[i]);
	}
	printf("\n");
	QuickSort(a, 0, n - 1);
	printf("\nAfter Sorting: ");
	for (int i = 0; i < SIZE; i++) {
		printf(" %d  ", a[i]);
	}
	return 0;

}

실행 결과

코드 이해는 쉽지만  그림으로 따라가려니 복잡한 알고리즘이었다.