본문 바로가기
자료구조와 알고리즘/알고리즘

퀵 정렬

by oncerun 2020. 8. 13.
반응형

 

퀵 정렬(Quick Sort)

 

버블 정렬, 선택 정렬, 삽입 정렬 알고리즘은 모두 시간 복잡도 O(N^2)을 가지기 때문에 데이터의 개수가 많을수록 사용하기 힘든 알고리즘입니다. 더욱 빠른 정렬 알고리즘이 필요한데 그중 하나인 퀵 정렬입니다.


퀵 정렬은 말 그대로 엄청나게 빠른 정렬 기법입니다. 이 퀵 정렬은 분할 정복(Divide and Conquer)에 근거하며,

퀵 정렬은 다른 정렬과는 달리 기준값을 하나 택하고 순회를 돌면서 기준값보다 작은 데이터는 좌측에, 기준값보다 큰 데이터는 우측으로 분할하고 다시 퀵 정렬을 적용합니다.

 

이러한 기준값을 피벗(Pivot)이라고도 하는데 보통  첫 번째 원소를 피벗 값으로 설정하고 사용합니다.

 

 

위 그림에서의 과정을 글로 나타내면 아래와 같습니다.

 

 5를 기준값으로 선택하여 그보다 작은 값은 왼쪽으로 큰 값들은 오른쪽으로 정렬한다.

 

맨 처음에 기준값을 택하고 작은 값은 좌측에 큰 값은 우측에 배치함으로써 작은 값과 큰 값으로 분할하고 분할된 두 영역이 A, B라고 한다면 A 영역에서 분할할 수 없을 때까지 기준값을 택하고 분할되며 B 영역도 마찬가지로 B 영역에서 분할할 수 없을 때까지 기준값을 택하고 분할되는 과정을 반복합니다. 이러한 퀵 정렬의 평균 복잡도는 아래와 같습니다.

퀵 정렬의 평균 복잡도:

최악의 경우 퀵 정렬의 복잡도:



퀵 정렬은 보통 재귀 함수를 이용하여 구현합니다.

 

import java.util.Arrays;
import java.util.Scanner;

public class QuickSort {
	

	public static void main(String[] args) {
		
		System.out.println("퀵정렬");
		
		Scanner scan = new Scanner(System.in);
		String value = scan.nextLine();
		
		
		String[] arr = value.split(" ");
		int[] array = new int[arr.length];
		
		for(int i = 0; i < arr.length; i++) {
			
			array[i] = Integer.parseInt(arr[i]);
			
		}
		
		
		long startTime = System.nanoTime();
		quickSort(0,array.length-1,array);
		long endTime = System.nanoTime();
		
		System.out.println(endTime - startTime);
		System.out.println(Arrays.toString(array));
	}
	
	public static void quickSort(int start,int end,int[] data) {
		//start는 정렬을 수행하는 첫번째 부분집합
		//end는 정렬을 수행하는 두번째 부분집합
		
		if(start >= end) {
			//원소가 한개인경우
			return;
		}
		int key = start; //키는 첫번째 원소
		int i = start + 1; //왼쪽부터 하나씩 키값보가 큰값을 찾을때 그 인덱스
		int j = end; //오른쪽 부터 하나씩 키값보다 작은값을 찾을때 그 인덱스
		int temp;
		
		while(j >= i) {
				//엇갈릴 때 까지 반복하며 엇갈린다면 왼쪽의 요소를 피벗값과 변경한다.
			while(i <= end && data[i] <= data[key]) { //피벗값보다 큰값을 찾는다.
				i++;
			}
			while(data[j] >= data[key] && j > start ) {//피벗값보다 작은값을 찾는다.
				j--;
			}
			
			if(j < i) { //엇갈렸다면
				temp = data[j]; 
				data[j] = data[key];
				data[key] = temp;
			}else {
				temp = data[j];
				data[j] = data[i];
				data[i] = temp;
			}
		}
		//j는 현재 인덱스 
		//start는 정렬된 배열의 첫번째 요소값
		quickSort(start, j-1,data);
		quickSort(j+1,end,data);
	}

}

 

퀵정렬에도 치명적인 단점이 존재합니다. 이미 정렬이 되어 있는 경우에는 분할 정복의 이점을 사용하지 못하기 때문에 n^2의 시간 복잡도를 나타냅니다.

반응형

'자료구조와 알고리즘 > 알고리즘' 카테고리의 다른 글

탐욕 알고리즘  (0) 2020.09.08
너비 우선 탐색 && 깊이 우선 탐색  (0) 2020.09.08
병합 정렬  (0) 2020.09.07
3. 삽입정렬  (0) 2020.08.11
2.버블정렬  (0) 2020.03.09

댓글