Notice
Recent Posts
Recent Comments
Link
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | ||||||
| 2 | 3 | 4 | 5 | 6 | 7 | 8 |
| 9 | 10 | 11 | 12 | 13 | 14 | 15 |
| 16 | 17 | 18 | 19 | 20 | 21 | 22 |
| 23 | 24 | 25 | 26 | 27 | 28 | 29 |
| 30 |
Tags
- stream
- Algorithm
- Stack
- 메모리구조
- coding test
- JSON
- s
- 혼자 공부하는 C언어
- datastructure
- buffer
- 알기쉬운 알고리즘
- list 컬렉션
- Serialization
- insertion sort
- 이스케이프 문자
- C programming
- 윤성우의 열혈 자료구조
- 윤성우 열혈자료구조
- Selection Sorting
- C 언어 코딩 도장
- R
- 이것이 자바다
- Graph
Archives
- Today
- Total
Engineering Note
Quick Sort 본문
퀵 정렬
- 퀵 정렬은 병합 정렬과 마찬가지로 '분할 정복(divide and conquer')에 근거하여 만들어진 정렬 방법이다.
- 정렬의 대상이 되는 배열에서 하나의 원소를 고른다. 이 원소를 pivot이라고 한다.
- 피벗을 기준으로 앞에는 피벗보다 작은 원소를 뒤에는 큰 원소들이 오도록 피벗을 기준으로 배열을 둘로 나눈다.
- 둘로 나누어진 배열에 대해서 재귀(recursion)적으로 반복한다. 배열의 원소의 개수가 1이 될때 까지 반복한다.
- 퀵 정렬 세부 동작 과정
- left가 가리키는 값이 pivot이 가리키는 값보다 클 때까지 반복
- pivot이 가리키는 값과 left가 가리키는 값을 비교하여 left가 가리키는 값이 작기 때문에 left 우측으로 한칸 이동,
- 4(pivot)와 3을 비교해서 3이 4보다 작기 때문에 left 우측으로 한 칸 이동
- 4(pivot)과 2를 비교해서 2가 4보다 작기 때문에 left 우측으로 한 칸 이동
- pivot이 가리키는 값과 left가 가리키는 값을 비교하여 left가 가리키는 값이 작기 때문에 left 우측으로 한칸 이동,


- 다시 left가 가리키는 값과 pivot이 가리키는 값을 비교
- 퀵정렬 알고리즘 C코드 구현
#include <cstdio>
#include <cstdlib>
void Swap(int& a, int& b) {
int t = a;
a = b;
b = t;
}
void _Sort(int list[], int left, int right) {
if (left <= right) {
int pivot = left;
int i = left + 1;
int j = right;
while (i <= j)
{
while (list[pivot] > list[i])
++i;
while (list[pivot] < list[j])
--j;
if (i <= j) {
Swap(list[i], list[j]);
++i;
--j;
}
else
break;
}
Swap(list[pivot], list[j]);
_Sort(list, left, j - 1);
_Sort(list, j + 1, right);
}
}
//Sort는 퀵소트의 재귀적인 구현을 위한 매개변수를 모두 갖고 있지 않으므로
//위임함수를 만들어서 동작 시킴
void Sort(int list\[\], int size) {
_Sort(list, 0, size - 1);
}
void PrintList(int list\[\], int size) {
for (int i = 0; i < size; ++i) {
printf("%5d", list[i]);
}
printf("\n");
}
int main() {
//int list\[10\] = { 40,30,10,70,50,80,90,60 };
int list\[10\] = { 40,30,70,90,50,80,10,60 };
PrintList(list, 8);
Sort(list, 8);
PrintList(list, 8);
system("pause");
}Sort 인터페이스
- 배열의 주소와 배열의 크기만으로 quicksort 위임함수를 호출 하도록 구현
_Sort 인터페이스
- 재귀적으로 동작할 '배열의 주소, 시작 값, 끝 값'을 매개변수로 하는 함수
- 재귀 함수 동작을 멈출 조건은 피벗을 기준으로 배열을 점점 둘로 나눌 때 배열의 원소의 개수가 1개에서 한번 더 동작 하면 left값과 right값이 교차하게 된다. 이때 재귀함수 종료조건 즉, 반대의 경우는 계속 함수가 동작하도록 if문 구성
- 코드 가독성을 위해 do while 문으로 실행 일단 1~1 사이의 코드를 먼저 동작하고 i와 j가 교차 하지 않을 경우 값 교환
- do while 문으로 루프문 조건에 부합해 확인하고 교체하고 확인하고 교체하다가 해당 조건이 끝나면 이제 피벗함수를 옮기고 분할 한다는 내용으로 이해하기 좋음
- While 문이 아니라 do while 문으로 하는 이유는 j 값을 먼저 변화 시키고 pivot보다 큰값들만 있는 곳 바로 왼쪽에서 j를 위치시키고 do while이 빠져 나온 후 j위칭와 pivot을 교체 하기 위해서이다.
- do 내부 코드를 반복하는데 i와 l이 교차 하지 않을 때까지
- 여기서 swap조건 if와 while의 조건이 같음 하지만 목적은 다름
- while의 조건은 루프문을 빠져나갈 조건이고 if문은 Swap을 위한 조건이다.\
시간복잡도
- pivot과 left, right에서 찾은 원소들을 비교하는 횟수는 자료의 개수(N)에 비례한다.
- 그리고 위에서 한 행위가 배열의 범위가 분할 되면서 재귀 호출이 되는데 이것은 logN에 비례한다.
- 그래서 시간복잡도를 계산하면 O(NlogN)이 나온다.
파이썬 퀵정렬 코드
def quick_sort(arr):
if len(arr) <= 1:
return arr
pivot = arr[len(arr) // 2]
lesser_arr, equal_arr, greater_arr = [], [], []
for num in arr:
if num < pivot:
lesser_arr.append(num)
elif num > pivot:
greater_arr.append(num)
else:
equal_arr.append(num)
return quick_sort(lesser_arr) + equal_arr + quick_sort(greater_arr)
수행 과정 시각화
'Computer Science > Data Structure & Algorithm' 카테고리의 다른 글
| 알고리즘 (0) | 2021.02.14 |
|---|---|
| 분할정복 알고리즘 (0) | 2021.02.14 |
| Insertion Sorting (0) | 2021.01.09 |
| Selection Sorting (0) | 2021.01.09 |
| Bubble Sorting (0) | 2021.01.09 |
Comments
