퀵 정렬의 시간복잡도와 작동원리
퀵 정렬은 이름 그대로 빠른 알고리즘이다.
시간복잡도가 O(N * logN)이다.
- 2 ^ 10 = 1,000
- 2 ^ 20 = 1,000,000
- log2N -> N이 1,000,000 일 때? 20
3 7 8 1 5 9 6 10 2 4 -> 3을 기준으로 오른쪽을 봤을 때 3보다 큰값(7)과 왼쪽을 봤을 때 3보다 작은 값(2)를 바꾼다.
3 2 8 1 5 9 6 10 7 4 -> 다시 오른쪽과 왼쪽을 보면서 큰값과, 작은 값을 찾아 바꾼다.
3 2 1 8 5 9 6 10 7 4 -> 이번에 서로 엇갈렸다(작은 값의 인덱스가 큰 값의 인덱스보다 더 작을 때). 이럴때는 작은 값과 3을 바꾼다.
1 2 3 8 5 9 6 10 7 4 -> 3보다 왼쪽에 있는 값은 3보다 작다. 3의 오른쪽에 있는 값들은 3보다 크다. 즉, 한 번 왼쪽과 오른쪽을 분할한 것이다. 3은 정렬이 이루어진 것이다.
1 2 3 8 5 9 6 10 7 4 -> 왼쪽은 1이 피벗(기준값)이 된다. 오른쪽은 8이 피벗값이다. 왼쪽과 오른쪽에서 각각 큰값과 작은 값을 찾는다. 1을 기준으로 오른쪽으로 큰값은 2이고 오른쪽으로 작은값은 없으므로 자기자신을 선택한다. 이 경우는 아까와 같이 엇갈린 상태이므로 1과 자기자신을 바꾼다.
1 2 3 8 5 9 6 10 7 4 -> 2를 기준으로 피벗을 수행한다. 이 경우는 데이터가 한 개 이기 때문에 그대로 둔다.
1 2 3 8 5 9 6 10 7 4 -> 8을 기준으로 피벗을 수행한다. 큰값 9와 작은 값 4가 나온다. 위치를 서로 바꾼다.
1 2 3 8 5 4 6 10 7 9 -> 8을 기준으로 피벗을 수행한다. 큰값 10와 작은 값 7가 나온다. 위치를 서로 바꾼다.
1 2 3 8 5 4 6 7 10 9 -> 8을 기준으로 피벗을 수행한다. 이 번에는 엇갈렸기 때문에 8과 7을 바꾼다.
1 2 3 7 5 4 6 8 10 9 -> 8을 기준으로 작은값은 왼쪽 큰 값은 오른쪽에 있다. 7과 10이 피벗이 된다. 7을 피벗하면 큰값은 없고 작은 값은 6이다. 이 경우에도 엇갈렸기 때문에 7과 6을 바꾼다.
1 2 3 6 5 4 7 8 10 9 -> 7을 기준으로 왼쪽은 작은 값이 있다.
....
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
기존 선택정렬, 버블정렬들의 시간복잡도는 아래와 같다.
N ^ 2 = 10 * 10 = 100
아래는 분할정복을 사용하는 퀵 정렬이다.
1 2 3 4 5 => 5 * 5 = 25
6 7 8 9 10 => 5 * 5 = 25
25 + 25 = 50
퀵 정렬은 분할정복을 사용하여 잘게 쪼갠 다음 그 것들을 각자 정렬하고 나중에 합치게 된다.
시간복잡도 O(N * logN)에서 반으로 나누는 것은 logN이다. 데이터 개수는 N이다.
#include <stdio.h>
int number = 10;
int data[10] = {1, 10, 5, 8, 7 , 6, 4, 3, 2, 9};
void show(){
int i;
for(i = 0; i < number; i++){
printf("%d ", data[i]);
}
}
void quickSort(int *data, int start, int end){
if (start >= end){ //원소가 1개인 경우 종료시키기
return;
}
int key = start; //키는 첫번째 원소 => 1
int i = start + 1; //왼쪽부터 큰값을 찾을 때 인덱스(키값의 왼쪽) => 10
int j = end; //오른쪽에서 부터 인덱스 => 9
int temp;
while(i <= j){//엇갈리지 않을때 까지 반복.
//배열의 범위를 넘어가지않도록 하는 조건.
while(i <= end && data[i] <= data[key]){ //키 값보다 큰 값을 만날때까지 반복.
i++;
}
// 범위를 넘어가지 않도록 하는 조건.
while(j > start && data[j] >= data[key] ){ //키 값보다 작은 값을 만날때까지 반복.
j--;
}
if(i > j){// 현재 엇갈린 상태면 키 값과 교체
temp = data[j];
data[j] = data[key];
data[key] = temp;
}else{ // 엇갈리지 않았다면 i와 j를 교체
temp = data[i];
data[i] = data[j];
data[j] = temp;
}
}
quickSort(data, start, j - 1);
quickSort(data, j + 1, end);
}
int main(void){
quickSort(data, 0, number - 1);
show();
return 0;
}
'IT공부 > 알고리즘' 카테고리의 다른 글
병합정렬(Merge Sort) (0) | 2020.07.29 |
---|---|
기초 정렬 알고리즘 문제 풀이 (0) | 2020.07.28 |
삽입정렬 (0) | 2020.07.25 |
버블정렬 (0) | 2020.07.25 |
정렬의 개요와 선택정렬 (0) | 2020.07.25 |