티스토리 뷰
2020/03/20 - [Study/소프트웨어] - 컴퓨터 알고리즘 초급 #5 ( 힙정렬 in c )
컴퓨터 알고리즘 초급 #5 ( 힙정렬 in c )
힙 정렬 힙 정렬이란? - 힙의 특성을 이용한 정렬 수행시간 : 합병정렬과 동일한 O(nlogn), 삽입정렬과 동일한 제자리 정렬 (Sort in Place) 힙이란 ? - 완전 이진 트리에 가까운 형태 이진 트리란? - 각 ��
15051015.tistory.com
퀵 정렬 (Quicksort) : 피봇이라는 값을 기준으로 피봇보다 작은것은 왼쪽, 큰것은 오른쪽으로 보내는 파티셔닝이라는 작업을 반복해서 작은 숫자는 계속 왼쪽, 큰 숫자는 계속 오른쪽으로 보내서 정렬시키는 방법
Divide-and-Conquer paradigm을 사용 (작게 쪼개서 작은걸 연산함 , 그 결과를 합침)
퀵 정렬은 partition 을 이용하여 한다.
Partitioning
Pivot element 를 정하여
피봇의 왼쪽은 작거나 같은 것 오른쪽은 크거나 같은값을 넣는다.
이 Partitioning을 재귀적으로 반복한다.
피봇의 왼쪽에서 피봇을 또 잡고 다시 그 왼쪽에는 작은값 오른쪽에는 높은값을 넣는다
이러한 과정을 반복한다.
{ 2 , 8 , 7 , 1 , 3 , 5 , 6, 4 }
피봇아이템 : 4
4와 2 비교 (4보다 작으므로 회색)
8과 4 비교 (4보다 크므로 녹색)
7과 4 비교 (4보다 크므로 녹색)
1과 4 비교 (4보다 작으므로 회색)
3과 4 비교 (4보다 작으므로 회색)
5와 4 비교 (4보다 크므로 녹색)
6과 4 비교 (4보다 크므로 녹색)
여기서 만약 녹색이 나오다가 회색이나오면
첫번째 녹색과 회색의 자리를 바꾼다 (ex 1과 8의 자리를 바꾼 것)
반복, 최종적으로는 첫번째 녹색과 피봇값을 바꾼다.
그렇게되면 최종적으로 {2,1,3,4,7,5,6,8} 이 된다.
수행시간 : 한번의 파티셔닝에 N-1번 비교하므로 0(n)
그렇다면, 정렬될때까지 몇번의 파티셔닝을 수행하느냐가 관건이다.
길이가 N인 배열은 길이가 2/N인 배열로 쪼개지고, 그 배열은 4/N배열로 쪼개지고 이러한 파티셔닝을 Balanced partitioning 이라고 한다.
Balanced partitioning 수행시간 : O(nlgn)
Unbalanced partitioning
쪼개면 1과 n-1 , 1과 n-2 ... 된다.
Unbalanced partitioning 수행시간 : O(n^2)
즉 선택한 피봇보다 작은 숫자가 1개 밖에 없을 때 Unbalanced partitioning이다. 최악의 경우이다.
최악의 경우에 피하기 위해서는
배열에서 Pivot을 무작위로 뽑아낸다.
그렇게하면 배열되어있는 상태의 배열은 최악의 경우를 따르겠지만, 배열되어 있든 아니든 항상 우리가 기대하는 확률값을 가질 수 있기 때문에 랜덤으로 피봇을 뽑아옴으로써 최악의 경우를 피할 수 있다.
퀵 정렬 in c
#include <stdio.h>
#include <stdlib.h> //랜덤함수 호출
void Swap(int arr[], int a, int b) // a,b 스왑 함수
{
int temp = arr[a];
arr[a] = arr[b];
arr[b] = temp;
}
int Partition(int arr[], int left, int right)
{
int pivot = arr[left]; // 피벗의 위치는 가장 왼쪽에서 시작
int low = left + 1;
int high = right;
while (low <= high) // 교차되기 전까지 반복한다
{
while (low <= right && pivot >= arr[low]) // 피벗보다 큰 값을 찾는 과정
{
low++; // low를 오른쪽으로 이동
}
while (high >= (left+1) && pivot <= arr[high]) // 피벗보다 작은 값을 찾는 과정
{
high--; // high를 왼쪽으로 이동
}
if (low <= high)// 교차되지 않은 상태이면 스왑 과정 실행
{
Swap(arr, low, high); //low와 high를 스왑
}
}
Swap(arr, left, high); // 피벗과 high가 가리키는 대상을 교환
return high; // 옮겨진 피벗의 위치정보를 반환
}
void QuickSort(int arr[], int left, int right)
{
if (left <= right)
{
int pivot = Partition(arr, left, right); // 둘로 나누어서
QuickSort(arr, left, pivot - 1); // 왼쪽 영역을 정렬한다.
QuickSort(arr, pivot + 1, right); // 오른쪽 영역을 정렬한다.
}
}
//메인함수
int main()
{
int n,i;
int arr[100];
printf("몇개의 숫자로 정렬하시겠습니까?\n");
scanf("%d",&n);
for(i = 0 ; i < n ; i++)
arr[i]=rand()%1000;
printf("정렬전 배열 :");
for(i = 0 ; i < n ; i++)
printf("%d ", arr[i]);
printf("\n");
QuickSort(arr,0,n-1);
printf("정렬후 배열 :");
for(i = 0 ; i < n ; i++)
printf("%d ", arr[i]);
printf("\n");
return 0;
}
//출처 : https://coding-factory.tistory.com/137
'Study > 소프트웨어' 카테고리의 다른 글
argc, argv[] (0) | 2020.06.26 |
---|---|
정렬 알고리즘 수행시간 비교 (0) | 2020.05.18 |
컴퓨터 알고리즘 초급 #6 ( 힙 정렬 in c ) 2 (0) | 2020.05.13 |
ㄹ 모양으로 숫자 프린트하기 in c (0) | 2020.04.01 |
컴퓨터 알고리즘 초급 #5 ( 힙정렬 in c ) (1) | 2020.03.20 |