피봇을 정하여 해당 피봇보다 작은 값을 왼쪽에서부터 찾기 시작.
큰 값을 오른쪽에서부터 찾기 시작.
양쪽에서 진행 중 찾아지는 값들을 서로 위치 변경.
반복 중에 양쪽에서 비교하던 인덱스가 만나면 그 위치와 피봇 값을 교환.

이 과정에서 중간지점으로 이동된 피봇을 중심으로 양쪽에 부분집합이 생긴다.
각 부분집합마다 피봇을 다시 정하여 위의 과정을 반복한다.

자료가 균일하게 분포되어 있으면 log2(n)의 연산 횟수가 필요하다.
매번 정렬시마다 n만큼 비교하므로 O(nlog(n))의 평균 효율을 보인다.
데이터 이동 연산은 비교보다 적게 발생한다.

데이터가 불균형하게 분포되어 있으면 최악의 경우 n(2)의 효율성을 지닌다.

기존 피봇을 재사용하지 않고, 먼 곳에 있는 값을 교환하므로 효율이 우수하다.
최악의 경우 효율이 떨어지므로 일반적으로 피봇값은 데이터 중 중간값으로 한다.

데이터 교환은 계속 일어나므로 불안정 정렬이다.

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
// 퀵 정렬 함수
void QuickSort(int data[], int startIndex, int endIndex)
{
    int pivot = 0;
 
    // 재귀호출을 감안해서 index 정보를 매개변수로 전달받는다.
    if (startIndex < endIndex)
    {
        // 나누어진 부분에서 startIndex와 endIndex가 만나서 pivot과 교환된 인덱스를 반환.
        pivot = patitionQuickSort(data, startIndex, endIndex);
        // 반환된 pivot 인덱스를 기준으로 quicksort 반복
        QuickSort(data, startIndex, pivot - 1);
        QuickSort(data, pivot + 1, endIndex);
    }
}
 
// 실제 pivot 교환 부분
int patitionQuickSort(int data[], int startIndex, int endIndex)
{
    int pivotIndex = endIndex;
    int leftIndex = startIndex;
    int rightIndex = endIndex;
    int temp = 0;
 
    // 양쪽의 Index가 만나기 전까지 반복
    while (leftIndex < rightIndex)
    {
        // left Index 이동, 두 Index가 만나기 전까지 Pivot보다 큰 값을 찾는다.
        while ((data[leftIndex] < data[pivotIndex]) && (leftIndex < rightIndex))
        {
            leftIndex++;
        }
 
        // right Index 이동, 두 Index가 만나기 전까지 Pivot보다 작은 값을 찾는다.
        while ((data[rightIndex] > data[pivotIndex]) && (leftIndex < rightIndex))
        {
            rightIndex--;
        }
 
        // pivot보다 큰 값인 leftIndex와 작은 값인 rightIndex의 위치 변경.
        if (leftIndex < rightIndex)
        {
            temp = data[leftIndex];
            data[leftIndex] = data[rightIndex];
            data[rightIndex] = temp;
        }
    }
 
    // 두 Index가 만나는 곳과 Pivot의 값 변경
    temp = data[pivotIndex];
    data[pivotIndex] = data[rightIndex];
    data[rightIndex] = temp;
 
    // 새로운 pivot의 위치는 rightIndex이다.
    return rightIndex;
}
cs


'Development > Algorithm' 카테고리의 다른 글

선택정렬 (Selection Sort)  (0) 2018.12.19
알고리즘 (algorithm)  (0) 2018.12.19
Posted by KingCat

키 값을 선택하여 값을 이동한다.


오름차순으로 정렬시 제일 먼저 제일 작은 값이 와야하므로 데이터 내에서 가장 작은 키 값을 선택하여 제일 앞으로 보낸다.

나머지 데이터에서 가장 작은 값을 찾아서 이미 정렬된 키 값 다음 위치로 보낸다.

반복하여 제일 마지막 키 값이 남을 때까지 작은 키 값을 찾아 이미 정렬된 키 값 다음 위치로 보내는 동작을 반복한다.

마지막 키 값은 정렬되지 않아도 위치가 확정이므로 정렬이 끝난다.


비교 연산 : 두 개의 루프. 1. n개 만큼 비교 시작. 2. n-1개와 비교. 즉 비교에 n(2) 만큼의 효율.

이동 연산 : 두 값의 위치 변경. temp 변수 포함 3번의 이동 연산. 즉 이동에 3n = n 만큼의 효율.


최종 n(2)+n 이므로 O(n(2))의 효율을 지닌다.


상대적으로 느린 알고리즘. 

이동 연산 자체는 n의 효율이므로 이동해야하는 데이터가 큰 경우 유리하다.

데이터가 이동이 계속 되므로 불안정성 정렬이다.


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
// 선택 정렬 함수
void SelectionSort(int data[], int cnt)
{
    int minIndex = 0, temp = 0;
    int i = 0, j = 0;
 
    // 첫번째 루프 : n-1만큼 비교
    for (i = 0; i < cnt - 1; i++)
    {
        minIndex = i;
 
        // 두번째 루프 : n개만큼 비교
        for (j = i + 1; j < cnt; j++)
        {
            if (data[j] < data[minIndex])
            {
                minIndex = j;
            }
        }
 
        // 이동 연산 : 3n
        if (minIndex != i)
        {
            temp = data[i];
            data[i] = data[minIndex];
            data[minIndex] = temp;
        }
    }
}
cs


'Development > Algorithm' 카테고리의 다른 글

퀵정렬 (QuickSort)  (0) 2018.12.19
알고리즘 (algorithm)  (0) 2018.12.19
Posted by KingCat

알고리즘은 시간 복잡도와 공간 복잡도로 나눔.

공간 복잡도는 필요한 하드디스크 기준이므로 현대에는 크게 신경쓰지 않음.

시간 복잡도는 입력 값에 따른 연산 횟수를 표현하므로 시간 복잡도 함수의 최고 차항 만으로 성능을 표현. (최고 차항을 제외한 다른 값들은 비율상 미비함으로)

빅오 표기법은 시간 복잡도 함수의 상한을 표현. (최소한 빅오 성능 이상을 보장)


오름차순 정렬 : 작은 키 값부터 올라간다.

내림차순 정렬 : 큰 키 값부터 내려온다.


정렬은 비교 - 이동 과정을 거친다.

비교 연산 성능이 같더라도 비교 후 이동해야 하는 자료의 크기가 크다면 이동이 적은 정렬이 성능이 좋다.

자료가 저장된 상태에 따라 평균 효율성과 최악 효율성에 차이가 있다면 이 또한 알고리즘 선택의 기준이 된다.


한번의 정렬시 기존 자료의 순서가 유지되면 안정 정렬

정렬 후 기존 자료의 순서가 뒤바뀌면 불안정 정렬

여러 키를 가지고 정렬을 해야할 경우 안정 정렬은 키만 바꾸면서 정렬을 여러번하면 자동으로 다중키 정렬이 된다.

불안정 정렬은 자료의 순서가 유지되지 않으므로 다중 키 정렬시 별도의 비교 로직이 필요하다.


키 값 비교 후 자료 교환 : 선택, 퀵, 버블 정렬

자료를 나누고 병합 : 병합 정렬

키 값을 여러 부분집합으로 분배하고 이를 이용해 정렬 : 기수 정렬

키 값을 비교 후 삽입 : 삽입, 셀 정렬

트리같은 특정 자료구조를 통한 정렬 : 히프 정렬


메모리에 자료를 모두 로딩 후 정렬하는 내부 정렬

보조 기억 장치에서 정렬을 수행하는 외부 정렬

내부 정렬은 빠르지만, 한번에 로딩 불가능한 대용량은 정렬 불가능

외부 정렬은 느리지만, 대용량의 자료를 정렬 가능

'Development > Algorithm' 카테고리의 다른 글

퀵정렬 (QuickSort)  (0) 2018.12.19
선택정렬 (Selection Sort)  (0) 2018.12.19
Posted by KingCat