Moglobin's
article thumbnail

Sorting

입력: 배열 A [ 1...n ] 의 수들

출력: A의 원소들을 갖는 B[1] ≤ B[2] ≤ … ≤ B[n] 의 배열 B

 

=> 이를 어떻게 하면 효율적으로 수행할 수 있을까?

 

 

* Sorting의 응용분야

 

- MP3 라이브러리 정렬하기

- 전화번호부 관리

- 정렬함으로써 쉬워지는 문제들: 중간값 찾기, 가장 가까운 수 찾기, 이진탐색, 큰 오차값 걸러내기

- 데이터 압축 => 정렬로 복제품을 찾을수도 있음

- 컴퓨터 그래픽스에서의 렌더링

 

Insertion Sort ( 삽입 정렬 )

삽입정렬(insertion sort)은 자료 배열의 모든 요소를 앞에서부터 차례대로 이미 정렬된 배열 부분과 비교하여, 자신의 위치를 찾아 삽입함으로써 정렬을 완성하는 알고리즘이다. 

 

k번째 반복 후의 결과 배열은, 앞쪽 k+1 항목이 정렬된 상태이다.

 

삽입 정렬의 애니메이션

 

Insertion Sort의 러닝타임 (복잡도)

1. movement of keys : Θ(n) steps

2. 결과적으로는 n번 바꾸기 * n개 (최대의 경우)

 

=>? Θ(n^2) because Θ(n^2) compares and Θ(n^2) swaps 

 

 

Insertion Sort 소스코드 

> C

void insertion_sort ( int *data, int n )
{
  int i, j, remember;
  for ( i = 1; i < n; i++ )
  {
    remember = data[(j=i)];
    while ( --j >= 0 && remember < data[j] ){
        data[j+1] = data[j];
        data[j] = remember;
    }
  }
}

> C++

#include <iterator>

template<typename biIter>
void insertion_sort(biIter begin, biIter end)
{
    biIter bond = begin;
    for (++bond; bond!=end; ++bond)
    {
      typename std::iterator_traits<biIter>::value_type key = *bond;
      biIter ins = bond;
      biIter pre = ins;
      for (--pre; ins != begin && *pre > key; *ins-- = *pre--);
      *ins = key;
    }
}

Binary Insertion Sort

이미 정렬된 sub 배열 A[ 1.. j-1 ]에 A[j]를 삽입. 

 

Binary insertion sort employs a binary search to determine the correct location to insert new elements, and therefore performs ⌈log2 n⌉ comparisons in the worst case. When each element in the array is searched for and inserted this is O(n log n). The algorithm as a whole still has a running time of O(n2) on average because of the series of swaps required for each insertion.

 

Binary search with take Θ(log n) time.

However, shifting the elements after insertion will still take Θ(n) time.

Complexity: Θ(n log n) comparisons Θ (n 2) swaps

 

 

Merge Sort ( 병합 정렬)

병합정렬(merge sort)은 O(nlogn) 비교 기반 정렬 알고리즘이다. 일반적인 방법으로 구현했을 때 이 정렬은 안정 정렬에 속하며, 분할 정복 알고리즘의 하나이다. 존 폰 노이만이 1945년에 개발했다. 

Merge Sort의 알고리즘

 

n-way 병합 정렬:

 

1. 정렬되지 않은 리스트를 각각 하나의 원소만 포함하는 n개의 부분리스트로 분할한다. (한 원소만 든 리스트는 정렬된 것과 같으므로)

2. 부분리스트가 하나만 남을 때까지 반복해서 병합하며 정렬된 부분리스트를 생성한다. 마지막 남은 부분리스트가 정렬된 리스트이다.

 

하향식 2-way 병합 정렬:

 

1. 리스트의 길이가 1 이하이면 이미 정렬된 것으로 본다. 그렇지 않을 경우에는,

2. 분할(divide): 정렬되지 않은 리스트를 절반으로 잘라 비슷한 크기의 두 부분 리스트로 나눈다.

3. 정복(conquer): 각 부분 리스트를 재귀적으로 합병 정렬을 이용해 정렬한다 .

4. 결합(combine): 두 부분 리스트를 다시 하나의 정렬된 리스트로 합병한다. 이때 정렬 결과가 임시배열에 저장된다.

5. 복사(copy): 임시 배열에 저장된 결과를 원래 배열에 복사한다.

 

Merge Sort 분석

 

 

 

Q: What is one advantage of insertion sort over merge sort?

A: We have to make a copy for an array, need extra space for it.

Merge Sort 구현

> 톱-다운

// Array A[] has the items to sort; array B[] is a work array.
TopDownMergeSort(A[], B[], n)
{
    CopyArray(A, 0, n, B);           // duplicate array A[] into B[]
    TopDownSplitMerge(B, 0, n, A);   // sort data from B[] into A[]
}

// Sort the given run of array A[] using array B[] as a source.
// iBegin is inclusive; iEnd is exclusive (A[iEnd] is not in the set).
TopDownSplitMerge(B[], iBegin, iEnd, A[])
{
    if(iEnd - iBegin < 2)                       // if run size == 1
        return;                                 //   consider it sorted
    // split the run longer than 1 item into halves
    iMiddle = (iEnd + iBegin) / 2;              // iMiddle = mid point
    // recursively sort both runs from array A[] into B[]
    TopDownSplitMerge(A, iBegin,  iMiddle, B);  // sort the left  run
    TopDownSplitMerge(A, iMiddle,    iEnd, B);  // sort the right run
    // merge the resulting runs from array B[] into A[]
    TopDownMerge(B, iBegin, iMiddle, iEnd, A);
}

//  Left source half is A[ iBegin:iMiddle-1].
// Right source half is A[iMiddle:iEnd-1   ].
// Result is            B[ iBegin:iEnd-1   ].
TopDownMerge(A[], iBegin, iMiddle, iEnd, B[])
{
    i = iBegin, j = iMiddle;

    // While there are elements in the left or right runs...
    for (k = iBegin; k < iEnd; k++) {
        // If left run head exists and is <= existing right run head.
        if (i < iMiddle && (j >= iEnd || A[i] <= A[j])) {
            B[k] = A[i];
            i = i + 1;
        } else {
            B[k] = A[j];
            j = j + 1;
        }
    }
}

CopyArray(A[], iBegin, iEnd, B[])
{
    for(k = iBegin; k < iEnd; k++)
        B[k] = A[k];
}

 

>바텀-업

// array A[] has the items to sort; array B[] is a work array
void BottomUpMergeSort(A[], B[], n)
{
    // Each 1-element run in A is already "sorted".
    // Make successively longer sorted runs of length 2, 4, 8, 16... until whole array is sorted.
    for (width = 1; width < n; width = 2 * width)
    {
        // Array A is full of runs of length width.
        for (i = 0; i < n; i = i + 2 * width)
        {
            // Merge two runs: A[i:i+width-1] and A[i+width:i+2*width-1] to B[]
            // or copy A[i:n-1] to B[] ( if(i+width >= n) )
            BottomUpMerge(A, i, min(i+width, n), min(i+2*width, n), B);
        }
        // Now work array B is full of runs of length 2*width.
        // Copy array B to array A for next iteration.
        // A more efficient implementation would swap the roles of A and B.
        CopyArray(B, A, n);
        // Now array A is full of runs of length 2*width.
    }
}

//  Left run is A[iLeft :iRight-1].
// Right run is A[iRight:iEnd-1  ].
void BottomUpMerge(A[], iLeft, iRight, iEnd, B[])
{
    i = iLeft, j = iRight;
    // While there are elements in the left or right runs...
    for (k = iLeft; k < iEnd; k++) {
        // If left run head exists and is <= existing right run head.
        if (i < iRight && (j >= iEnd || A[i] <= A[j])) {
            B[k] = A[i];
            i = i + 1;
        } else {
            B[k] = A[j];
            j = j + 1;
        }
    }
}

void CopyArray(B[], A[], n)
{
    for(i = 0; i < n; i++)
        A[i] = B[i];
}

'컴공' 카테고리의 다른 글

Lecture 4: Heaps and Heap Sort  (0) 2021.07.23
03. Vector Calculus (P)Review  (0) 2021.07.22
Lecture 2: Models of Computation (연산을 위한 모델들)  (0) 2021.07.11
02. Linear Algebra (P)Review  (0) 2021.07.05
01. Course Overview  (0) 2021.07.05
profile

Moglobin's

@슈플로프

Take your time 🍋