[자료구조] 퀵/삽입/히프/트리 정렬
1) 퀵 정렬
- 정렬할 전체 원소에 대해서 정렬을 수행하지 않고, 기준 값을 중심으로 왼쪽 부분 집합과 오른쪽 부분집합으로 분할하여 정렬하는 방법
 - 왼쪽 부분집합에는 기준 값보다 작은 원소들을 이동시키고, 오른쪽 부분집합에는 기준 값보다 큰 원소들을 이동시킴
 - 기준 값: 피봇(Pivot)
 
수행 과정
- 분할(Divide)
    
- 정렬할 자료들을 기준 값을 중심으로 2개의 부분집합으로 분할하기
 - 부분집합으로 분할하기 위해서 L과 R을 사용
 
- Step 1 : 왼쪽 끝에서 오른쪽으로 움직이면서 크기를 비교하여 피봇 보다 크거나 같은 원소를 찾아 L로 표시함
 - Step 2 : 오른쪽 끝에서 왼쪽으로 움직이면서 피봇 보다 작은 원소를 찾아 R로 표시함
 - Step 3 : L이 가리키는 원소와 R이 가리키는 원소를 서로 교환함
 
 - 정복(Conquer)
    
- 부분집합의 원소들 중에서 기준 값보다 작은 원소들은 왼쪽 부분집합으로, 기준 값보다 큰 원소들은 오른쪽 부분집합으로 정렬하기
 - 부분집합의 크기가 1 이하로 충분히 작지 않으면 순환 호출을 이용하여 다시 분할
 
- Step 1 : L과 R이 만나게 되면 피봇과 R의 원소를 서로 교환하고, 교환한 위치를 피봇의 위치로 확정함
 - Step 2 : 피봇의 확정된 위치를 기준으로 만들어진 새로운 왼쪽 부분집합과 오른쪽 부분집합에 대해서 퀵 정렬을 순환적으로 반복 수행함
 - Step 3 : 모든 부분집합의 크기가 1 이하가 되면 퀵 정렬을 종료함
 
 








partition(a[], begin, end)
{
    pivot = (begin + end) / 2;
    L = begin;
    R = end;
    while(L < R)
    {
        while (a[L] < a[pivot] && L < R)   L++;
        while (a[R] < a[pivot] && L < R)   R--;
        if(L < R)   // L의 원소와 R의 원소 교환
        {
            temp = a[L];
            a[L] = a[R];
            a[R] = temp;
        }
    }
    temp = a[pivot];    // R의 원소와 피봇 원소 교환
    a[pivot] = a[R];
    a[R] = temp;
    return R;
}
메모리 사용 공간
- n개의 원소에 대하여 n개의 메모리 사용
 
연산 시간
- 최선의 경우 :
    
- 피봇에 의해서 원소들이 왼쪽 부분집합과 오른쪽 부분집합으로 정확히 n/2개씩 이등분이 되는 경우가 반복되어 수행 단계 수가 최소가 되는 경우
 
 - 최악의 경우 :
    
- 피봇에 의해 원소들을 분할하였을 때 1개와 n-1개로 한쪽으로 치우쳐 분할되는 경우가
 - 반복되어 수행 단계 수가 최대가 되는 경우
 
 - 평균 시간 복잡도 : O(nlgn)
 - 같은 시간 복잡도를 가지는 다른 정렬 방법에 비해서 자리 교환 횟수를 줄임으로써 더 빨리 실행되어 실행 시간 성능이 좋은 정렬 방법임
 
2) 삽입 정렬
- 정렬되어있는 부분집합에 정렬할 새로운 원소의 위치를 찾아 삽입하는 방법
 - 정렬할 자료를 두 개의 부분집합 S와 U로 가정
    
- 부분집합 S : 정렬된 앞부분의 원소들
 - 부분집합 U : 아직 정렬되지 않은 나머지 원소들
 
 - 정렬되지 않은 부분집합 U의 원소를 하나씩 꺼내서 이미 정렬되어 있는 부분집합 S의 마지막 원소부터 비교하면서 위치를 찾아 삽입
 - 삽입 정렬을 반복하면서 부분집합 S의 원소는 하나씩 늘리고 부분집합 U의 원소는 하나씩 감소하게 함.
 - 부분집합 U가 공집합이 되면 삽입 정렬이 완성됨
 
수행 과정



…..

insertionSort(a[], n)
{
    for (int i=1; i<n; i++) 
    {
        temp = a[i];
        j = i;
        if (a[j=1] > temp)  move = true;
        else move = false;
        while (move)
        {
            a[j] = a[j–1];
            j--;
            if (j>0 && a[j-1] > temp)   move = true;
            else move = false;
        }
    }
    a[j] = temp; 
}
메모리 사용 공간
- n개의 원소에 대하여 n개의 메모리 사용
 
연산 시간
- 최선의 경우 :
    
- 원소들이 이미 정렬되어 있어서 비교 횟수가 최소인 경우
 - 이미 정렬되어있는 경우에는 바로 앞자리 원소와 한번만 비교함
 - 전체 비교 횟수 = n-1
 - 시간 복잡도: O(n)
 
 - 최악의 경우 :
    
- 모든 원소가 역순으로 되어있어서 비교 횟수가 최대인 경우
 - 전체 비교 횟수 = 1 + 2 + 3 + ⋯ + (n-1) = n(n-1)/2
 - 시간 복잡도 : O(n^2)
 - 삽입 정렬의 평균 비교 횟수 = n(n-1)/4
 - 평균 시간 복잡도 : O(n^2)
 
 
3) 히프 정렬
- 히프 자료구조를 이용한 정렬 방법
 - 히프에서는 항상 가장 큰 원소가 루트 노드가 되고 삭제 연산을 수행하면 항상 루트 노드의 원소를 삭제하여 반환
    
- 최대 히프에 대해서 원소의 개수만큼 삭제 연산을 수행하여 내림차순으로 정렬 수행
 - 최소 히프에 대해서 원소의 개수만큼 삭제 연산을 수행하여 오름차순으로 정렬 수행
 
 
수행 과정



…

메모리 사용 공간
- 원소 n개에 대하여 n개의 메모리 공간 사용
 - 크기 n의 히프 저장 공간 사용
 
연산 시간
- 히프 재구성 연산 시간 :
    
- 완전 이진 트리를 히프로 구성하는 평균 시간은 O(lgn)
 - n개의 노드에 대해서 n번의 히프 재구성 작업 수행
 
 - 평균 시간 복잡도 : O(nlgn)
 
4) 트리 정렬
- 이진 탐색 트리를 이용하여 정렬하는 방법
 - 중위 우선 순회
 
수행 과정
- 정렬할 원소들을 이진 탐색 트리로 구성함
 - 이진 탐색 트리를 중위 우선 순회함 중위 순회 경로가 오름차순 정렬이 됨
 

메모리 사용 공간
- 원소 n개에 대해서 n개의 메모리 공간 사용
 - 크기 n의 이진 탐색 트리 저장 공간
 
연산 시간
- 노드 한 개에 대한 이진 탐색 트리 구성 시간 : O(lgn)
 - n개의 노드에 대한 시간 복잡도 : O(n)