Presentation is loading. Please wait.

Presentation is loading. Please wait.

C언어 응용 제 13 주 그래프2, 정렬.

Similar presentations


Presentation on theme: "C언어 응용 제 13 주 그래프2, 정렬."— Presentation transcript:

1 C언어 응용 제 13 주 그래프2, 정렬

2 다음 주 과제 10장 읽어오기 숙제 해서 제출하기

3 그래프 그래프의 구조 그래프의 구현 그래프 순회 신장 트리와 최소 비용 신장 트리

4 지난주 내용 그래프의 인접행렬 표현 그래프의 인접리스트 표현 그래프의 탐색 깊이우선탐색 너비우선탐색

5 이번 주 내용

6 신장 트리(spanning tree) 그래프 G1과 신장 트리의 예
n개의 정점으로 이루어진 무방향 그래프 G에서 n개의 모든 정점과 n-1개의 간선으로 만들어진 트리 그래프 G1과 신장 트리의 예 [그림 9-13] 그래프 G1과 신장 트리의 예

7 깊이 우선 신장 트리(depth first spanning tree)
깊이 우선 탐색을 이용하여 생성된 신장 트리 너비 우선 신장 트리(breadth first spanning tree) 너비 우선 탐색을 이용하여 생성된 신장 트리 그래프 G1의 깊이 우선 신장 트리와 너비 우선 신장 트리 [그림 9-14] 그래프 G9의 신장 트리

8 최소 비용 신장 트리(minimum cost spanning tree)
무방향 가중치 그래프에서 신장 트리를 구성하는 간선들의 가중치 합이 최소인 신장 트리 가중치 그래프의 간선에 주어진 가중치 비용이나 거리, 시간을 의미하는 값 최소 비용 신장 트리를 만드는 알고리즘 Kruskal 알고리즘 Prime 알고리즘

9 Kruskal 알고리즘Ⅰ 가중치가 높은 간선을 제거하면서 최소 비용 신장 트리를 만드는 방법
⑴ 그래프 G의 모든 간선을 가중치에 따라 내림차순으로 정리한다. ⑵ 그래프 G에서 가중치가 가장 높은 간선을 제거한다. 이때 정점을 그래프에서 분리시키는 간선은 제거할 수 없으므로 이런 경우에는 그 다음으로 가중치가 높은 간선을 제거한다. ⑶ 그래프 G에 n-1개의 간선만 남을 때까지 ⑵를 반복한다. ⑷ 그래프에 n-1개의 간선이 남게 되면 최소 비용 신장 트리가 완성된다.

10 Kruskal 알고리즘Ⅰ을 이용하여 G10의 최소 비용 신장 트리 만들기

11 ① 가중치가 가장 큰 간선 (A,C) 제거. (현재 남은 간선의 수 : 10개)

12 ② 남은 간선 중에서 가중치가 가장 큰 간선 (F,G) 제거
(현재 남은 간선의 수 : 9개)

13 ③ 남은 간선 중에서 가중치가 가장 큰 간선 (B,G) 제거
(현재 남은 간선의 수 : 8개)

14 ④ 남은 간선 중에서 가중치가 가장 큰 간선 (C,E) 제거
(현재 남은 간선의 수 : 7개)

15 현재 남은 간선의 수가 6개 이므로 알고리즘 수행을 종료하고 신장 트리 완성
⑤ 남은 간선 중에서 가중치가 가장 큰 간선 (D,E)를 제거하면, 그래프가 분리되어 단절 그래프가 되므로, 그 다음으로 가중치가 큰 간선 (C,F)를 제거해야 한다. 그런데 간선 (C,F)를 제거하면 정점 C가 분리되므로 제거할 수 없으므로, 다시 그 다음으로 가중치가 큰 간선 (A,D)를 제거한다. (현재 남은 간선의 수 : 6개) 현재 남은 간선의 수가 6개 이므로 알고리즘 수행을 종료하고 신장 트리 완성

16 G10의 최소 비용 신장 트리 [그림 9-15] Kruskal 알고리즘Ⅰ을 이용하여 완성된 G10의 최소 비용 신장 트리

17 Kruskal 알고리즘 Ⅱ 가중치가 낮은 간선을 삽입하면서 최소 비용 신장 트리를 만드는 방법 Kruskal 알고리즘Ⅱ
⑴ 그래프 G의 모든 간선을 가중치에 따라 오름차순으로 정리한다. ⑵ 그래프 G에 가중치가 가장 작은 간선을 삽입한다. 이때 사이클을 형성하는 간선은 삽입할 수 없으므로 이런 경우에는 그 다음으로 가중치가 작은 간선을 삽입한다. ⑶ 그래프 G에 n-1개의 간선을 삽입할 때까지 ⑵를 반복한다. ⑷ 그래프 G의 간선이 n-1개가 되면 최소 비용 신장 트리가 완성된다.

18 Kruskal 알고리즘 Ⅱ를 이용하여 G10의 최소 비용 신장 트리 만들기

19 ① 가중치가 가장 작은 간선 (E,G) 삽입. (현재 삽입한 간선의 수 : 1개)

20 ② 나머지 간선 중에서 가중치가 가장 작은 간선 (A,B) 삽입.
(현재 삽입한 간선의 수 : 2개)

21 ③ 나머지 간선 중에서 가중치가 가장 작은 간선 (E,F) 삽입.
(현재 삽입한 간선의 수 : 3개)

22 ④ 나머지 간선 중에서 가중치가 가장 작은 간선 (B,D) 삽입.
(현재 삽입한 간선의 수 : 4개)

23 ⑤ 나머지 간선 중에서 가중치가 가장 작은 간선 (A,D)를 삽입하면 A-B-D의 사이클이 생성되므로 삽입할 수 없다
⑤ 나머지 간선 중에서 가중치가 가장 작은 간선 (A,D)를 삽입하면 A-B-D의 사이클이 생성되므로 삽입할 수 없다. 그 다음으로 가중치가 가장 작은 간선 (C,F) 삽입. (현재 삽입한 간선의 수 : 5개)

24 ⑥ 나머지 간선 중에서 가중치가 가장 작은 간선 (D,E) 삽입.
(현재 삽입한 간선의 수 : 6개) 현재 삽입한 간선의 수가 6개 이므로 알고리즘 수행을 종료하고 신장 트리 완성

25 G10의 최소 비용 신장 트리 [그림 9-16] Kruskal 알고리즘Ⅱ를 이용하여 완성된 G10의 최소 비용 신장 트리

26 Kruskal Algorithm II 의사코드

27 예제 4

28 간선 오름차순 정렬

29 구성 과정 Total Cost = =13

30 Prim 알고리즘 간선을 정렬하지 않고 하나의 정점에서 시작하여 트리를 확장해 나가는 방법
⑴ 그래프 G에서 시작 정점을 선택한다. ⑵ 선택한 정점에 부속된 모든 간선 중에서 가중치가 가장 작은 간선을 연결하여 트리를 확장한다. ⑶ 이전에 선택한 정점과 새로 확장된 정점에 부속된 모든 간선 중에서 가중치가 가장 작은 간선을 삽입한다. 이때 사이클을 형성하는 간선은 삽입할 수 없으므로 그 다음으로 가중치가 작은 간선을 선택한다. ⑷ 그래프 G에 n-1개의 간선을 삽입할 때까지 ⑶을 반복한다. ⑸ 그래프 G의 간선이 n-1개가 되면 최소 비용 신장 트리가 완성된다

31 Prim 알고리즘을 이용하여 G10의 최소 비용 신장 트리 만 들기
초기 상태 : 그래프 G10의 정점 중에서 정점 A를 시작 정점으 로 선택

32 ① 정점 A에 부속된 간선 중에서 가중치가 가장 작은 간선 (A,B)을 삽입하여 트리 확장.
(현재 삽입한 간선의 수 : 1개)

33 ② 현재 확장된 트리의 정점 A, B에 부속된 간선 중에서 가중치가 가장 작은 간선 (B,D)를 삽입하여 트리 확장.
(현재 삽입한 간선의 수 : 2개)

34 ③ 현재 확장된 트리의 정점 A, B, D에 부속된 간선 중에서 가중치가 가장 작은 간선 (A,D)를 삽입하면 A-B-D의 사이클이 생성되므로 삽입할 수 없다. 따라서 그 다음으로 가중치가 가장 작은 간선 (D,E) 삽입. (현재 삽입한 간선의 수 : 3개, 삽입 불가능한 간선 : (A,D))

35 ④ 현재 확장된 트리의 정점 A, B, D, E에 부속된 간선 중에서 가중치가 가장 작은 간선 (E,G)를 삽입하여 트리 확장.
(현재 삽입한 간선의 수 : 4개, 삽입 불가능한 간선 : (A,D))

36 ⑤ 현재 확장된 트리의 정점 A, B, D, E, G에 부속된 간선 중에서 가중치가 가장 작은 간선 (E,F)를 삽입하여 트리 확장.
(현재 삽입한 간선의 수 : 5개, 삽입 불가능한 간선 : (A,D))

37 ⑥ 현재 확장된 트리의 정점 A, B, D, E, F, G에 부속된 간선 중에서 가중치가 가장 작은 간선 (C,F)를 삽입하여 트리 확장.
(현재 삽입한 간선의 수 : 6개, 삽입 불가능한 간선 : (A,D)) 현재 남은 간선의 수가 6개 이므로 알고리즘 수행을 종료하고 신장 트리 완성.

38 G10의 최소 비용 신장 트리 [그림 9-17] Prime 알고리즘을 이용하여 완성된 G10의 최소 비용 신장 트리

39 Prim Algorithm 의사코드

40 예제 4

41 구성 과정 4

42 구성 과정 4

43 구성 과정 4

44 정렬 정렬 선택 정렬 버블 정렬 퀵 정렬 삽입 정렬 셸 정렬 병합 정렬 기수 정렬 히프 정렬 트리 정렬

45 자료의 정렬 방법을 알아본다. 정렬 방법에 대한 알고리즘을 이해한다. 정렬 알고리즘의 효율을 알아본다.

46 정렬(sort) 2개 이상의 자료를 작은 것부터 큰 것 순서의 오름차순(ascending)이나 큰 것부터 작은 것 순서의 내림차순(descending)으로 재배열하는 것 자료를 정렬하는데 사용하는 기준이 되는 특정 값 정렬의 예 [그림 10-1] 정렬의 예

47 정렬방법의 분류 실행 방법에 따른 분류 비교식 정렬(comparative sort) 분산식 정렬(distribute sort)
비교하고자 하는 각 키 값들을 한번에 두 개씩 비교하여 교환하는 방식으로 정렬을 실행하는 방법 분산식 정렬(distribute sort) 키 값을 기준으로 하여 자료를 여러 개의 부분 집합으로 분해하고, 각 부분집합을 정렬함으로써 전체를 정렬하는 방식으로 실행하는 방법

48 정렬 장소에 따른 분류 내부 정렬(internal sort) 내부 정렬 방식 외부 정렬(external sort)
정렬할 자료를 메인 메모리에 올려서 정렬하는 방식 정렬 속도가 빠르지만 정렬할 수 있는 자료의 양이 메인 메모리의 용량에 따라 제한됨 내부 정렬 방식 교환 방식 : 키를 비교하고 교환하여 정렬하는 방식(선택 정렬,버블 정렬, 퀵 정렬) 삽입 방식 : 키를 비교하고 삽입하여 정렬하는 방식(삽입 정렬, 쉘 정렬) 병합 방식 : 키를 비교하고 병합하여 정렬하는 방식 (2-way병합, n-way병합) 분배 방식 : 키를 구성하는 값을 여러 부분집합에 분배하여 정렬하는 방식(기수정렬) 선택 방식 : 이진 트리를 사용하여 정렬하는 방식 (히프 정렬, 트리 정렬) 외부 정렬(external sort) 정렬할 자료를 보조 기억장치에서 정렬하는 방식 대용량의 보조 기억 장치를 사용하기 때문에 내부 정렬보다 속도는 떨어지지만 내부 정렬로 처리할 수 없는 대용량의 자료에 대한 정렬 가능 외부 정렬 방식 병합 방식 : 파일을 부분 파일로 분리하여 각각을 내부 정렬 방법으로 정렬하여 병합하는 정렬 방식 (2-way 병합, n-way 병합)

49 선택 정렬(selection sort) 수행 방법
전체 원소들 중에서 기준 위치에 맞는 원소를 선택하여 자리를 교환하는 방식으로 정렬 수행 방법 전체 원소 중에서 가장 작은 원소를 찾아서 선택하여 첫 번째 원소와 자리를 교환 그 다음 두 번째로 작은 원소를 찾아 선택하여 두 번째 원소와 자리를 교환 그 다음에는 세 번째로 작은 원소를 찾아서 세 번째 원소와 자리를 교환 이 과정을 반복하면서 정렬을 완성

50 선택 정렬 수행 과정 정렬되지 않은 {69, 10, 30, 2, 16, 8, 31, 22}의 자료들을 선택 정렬 방법으로 정렬하는 과정을 살펴보자. ① 첫 번째 자리를 기준 위치로 정하고, 전체 원소 중에서 가장 작은 원소 2를 선택하여 기준 위치에 있는 원소 69와 자리 교환

51 ② 두 번째 자리를 기준 위치로 정하고, 나머지 원소 중에서 가장 작은 원소 8을 선택하여 기준 위치에 있는 원소 10과 자리 교환

52 ③ 세 번째 자리를 기준 위치로 정하고, 나머지 원소 중에서 가장 작은 원소 10을 선택하여 기준 위치에 있는 원소 30과 자리 교환

53 ④ 네 번째 자리를 기준 위치로 정하고, 나머지 원소 중에서 가장 작은 원소 16을 선택하여 기준 위치에 있는 원소 69와 자리 교환

54 ⑤ 다섯 번째 자리를 기준 위치로 정하고, 나머지 원소 중에서 가장 작은 원소 22를 선택하여 기준 위치에 있는 원소 69와 자리 교환

55 ⑥여섯 번째 자리를 기준 위치로 정하고, 나머지 원소 중에서 가장 작은 원소 30을 선택하여 기준 위치에 있는 원소 30과 자리 교환 (제자리)

56 ⑦ 일곱 번째 자리를 기준 위치로 정하고, 나머지 원소 중에서 가장 작은 원소 31을 선택하여 기준 위치에 있는 원소 31과 자리 교환. (제자리)
마지막에 남은 원소 69는 전체 원소 중에서 가장 큰 원소로서 이미 마지막 자리에 정렬된 상태이므로 실행을 종료하고 선택 정렬이 완성된다.

57 선택 정렬 알고리즘 selectionSort(a[],n) for (i←1; i<n; i←i+1) {
        a[i], ⋯,a[n-1] 중에서 가장 작은 원소 a[k]를 선택하여,         a[i]와 교환한다.      } end selectionSort()

58 선택 정렬 알고리즘 분석 메모리 사용공간 비교횟수 어떤 경우에서나 비교횟수가 같으므로 시간 복잡도는 𝑂( 𝑛 2 )이 된다.
n개의 원소에 대하여 n개의 메모리 사용 비교횟수 1단계 : 첫 번째 원소를 기준으로 n개의 원소 비교 2단계 : 두 번째 원소를 기준으로 마지막 원소까지 n-1개의 원소 비교 3단계 : 세 번째 원소를 기준으로 마지막 원소까지 n-2개의 원소 비교 i 단계 : i 번째 원소를 기준으로 n-i개의 원소 비교 어떤 경우에서나 비교횟수가 같으므로 시간 복잡도는 𝑂( 𝑛 2 )이 된다.

59 선택 정렬 C 프로그램 {69, 10, 30, 2, 16, 8, 31, 22}의 자료들을 선택 정렬 알고리즘을 사용하여 정렬하는 프로그램 실행 결과

60 다음 주 계속

61 버블 정렬(bubble sort) 인접한 두 개의 원소를 비교하여 자리를 교환하는 방식
첫 번째 원소부터 마지막 원소까지 반복하여 한 단계가 끝나면 가장 큰 원소가 마지막 자리로 정렬 첫 번째 원소부터 인접한 원소끼리 계속 자리를 교환하면서 맨 마지막 자리로 이동하는 모습이 물 속에서 물 위로 올라오는 물방울 모양과 같다고 하여 버블(bubble) 정렬이라 함.

62 버블 정렬 수행 과정 정렬되지 않은 {69, 10, 30, 2, 16, 8, 31, 22}의 자료들을 버블 정렬로 정렬하는 과정 ① 인접한 두 원소를 비교하여 자리를 교환하는 작업을 첫 번째 원소부터 마지막 원소까지 차례로 반복하여 가장 큰 원소 69를 마지막 자리로 정렬.

63 ② 버블 정렬로 나머지 원소 중에서 가장 큰 원소 31을 끝에서 두 번째 자리로 정렬

64 ③ 버블 정렬로 나머지 원소 중에서 가장 큰 원소 30을 끝에서 세 번째 자리로 정렬

65 ④ 버블 정렬로 나머지 원소 중에서 가장 큰 원소 22를 끝에서 네 번째 자리로 정렬

66 ⑤ 버블 정렬로 나머지 원소 중에서 가장 큰 원소 16을 끝에서 다섯 번째 자리로 정렬

67 ⑥ 버블 정렬로 나머지 원소 중에서 가장 큰 원소 10을 끝에서 여섯 번째 자리로 정렬

68 ⑦ 버블 정렬로 나머지 원소 중에서 가장 큰 원소 8을 끝에서 일곱 번째 자리로 정렬
마지막에 남은 첫 번째 원소는 전체 원소 중에서 가장 작은 원소로 이미 정렬된 상태이므로 실행을 종료하고 버블 정렬이 완성된다

69 버블 정렬 알고리즘 bubbleSort(a[],n) for (i←n-1; i≥0; i←i-1) {
        for (j←0; j<i; j←j+1) {             if (a[j]>a[j+1]) then {                 temp ← a[j];                 a[j] ← a[j+1];                 a[j+1] ← temp;             }         }      } end bubbleSort()

70 버블 정렬 알고리즘 분석 메모리 사용공간 연산 시간 n개의 원소에 대하여 n개의 메모리 사용
최선의 경우 : 자료가 이미 정렬되어있는 경우 비교횟수 : i번째 원소를 (n-i)번 비교하므로, n(n-1)/2 번 자리교환횟수 : 자리교환이 발생하지 않는다. 최악의 경우 : 자료가 역순으로 정렬되어있는 경우 자리교환횟수 : i번째 원소를 (n-i)번 교환하므로, n(n-1)/2 번 평균 시간 복잡도는 𝑂( 𝑛 2 )이 된다.

71 버블 정렬 C 프로그램 정렬할 자료 : {69, 10, 30, 2, 16, 8, 31, 22} 실행 결과

72 퀵 정렬(quick sort) 정렬할 전체 원소에 대해서 정렬을 수행하지 않고, 기준 값을 중심으로 왼쪽 부분 집합과 오른쪽 부분 집합으로 분할하여 정렬하는 방법 왼쪽 부분 집합에는 기준 값보다 작은 원소들을 이동시키고, 오른쪽 부분 집합에는 기준 값보다 큰 원소들을 이동시킨다. 기준 값 : 피봇(pivot) 일반적으로 전체 원소 중에서 가운데에 위치한 원소를 선택 퀵 정렬은 다음의 두 가지 기본 작업을 반복 수행하여 완성한다. 분할(divide) 정렬할 자료들을 기준값을 중심으로 2개의 부분 집합으로 분할하기 정복(conquer) 부분 집합의 원소들 중에서 기준값보다 작은 원소들은 왼쪽 부분 집합으로, 기준값보다 큰 원소들은 오른쪽 부분집합으로 정렬하기. 부분 집합의 크기가 1 이하로 충분히 작지 않으면 순환호출을 이용하여 다시 분할

73 퀵 정렬 수행 방법 부분 집합으로 분할하기 위해서 L과 R을 사용
L와 R이 만나게 되면 피봇과 R의 원소를 서로 교환하고, 교환한 위치를 피봇의 위치로 확정한다. 피봇의 확정된 위치를 기준으로 만들어진 왼쪽 부분 집합과 오른쪽 부분 집합에 대해서 퀵 정렬을 순환적으로 반복 수행하는데 부분 집합의 크기가 1 이하가 되면 퀵 정렬을 종료한다.

74 퀵 정렬 수행 과정 정렬되지 않은 {69, 10, 30, 2, 16, 8, 31, 22}의 자료들을 퀵 정렬로 정렬하는 과정
원소의 개수가 8개이므로 네 번째 자리에 있는 원소 2를 첫 번째 피봇으로 선택하고 퀵 정렬 시작 ① 원소 2를 피봇으로 선택하고 퀵 정렬 시작. L이 오른쪽으로 이동하면서 피봇보다 크거나 같은 원소를 찾고, R은 왼쪽으로 이동하면서 피봇보다 작은 원소를 찾는다. L은 원소 69를 찾고, R은 피봇 보다 작은 원소를 찾지 못한 채로 원소 69에서 L과 만난다. L과 R이 만났으므로, 원소 69를 피봇과 교환하여 피봇 원소 2의 위치를 확정한다

75 ② 피봇 2의 왼쪽 부분 집합은 공집합이므로 퀵 정렬을 수행하지 않고, 오른쪽 부분 집합에 대해서 퀵 정렬 수행
② 피봇 2의 왼쪽 부분 집합은 공집합이므로 퀵 정렬을 수행하지 않고, 오른쪽 부분 집합에 대해서 퀵 정렬 수행. 오른쪽 부분 집합의 원소가 7개 이므로 가운데 있는 원소 16을 피봇으로 선택. L이 찾은 30과 R이 찾은 8을 서로 교환한다

76 현재 위치에서 L과 R의 작업을 반복한다. L은 원소 69를 찾았지만, R은 피봇 보다 작은 원소를 찾지 못한 채로 원소 69에서 L과 만나게 된다. L과 R이 만났으므로, 원소 69를 피봇과 교환하여 피봇 원소 16의 위치를 확정한다

77 ③ 피봇 16의 왼쪽 부분 집합에서 원소 10을 피봇으로 선택하여 퀵 정렬 수행.
L의 원소 10과 R의 원소 8을 교환하는데, L의 원소가 피봇이므로 피봇 원소 10의 위치가 확정된다

78 ④ 피봇 10의 왼쪽 부분 집합의 원소가 한 개이므로 퀵 정렬을 수행하지 않고, 오른쪽 부분 집합은 공집합이므로 역시 퀵 정렬을 수행하지 않는다.
이제 1단계의 피봇이었던 원소 16의 오른쪽 부분 집합에 대해 퀵 정렬 수행. 오른쪽 부분 집합의 원소가 4개이므로 원소 30을 피봇으로 선택. L이 찾은 69와 R이 찾은 22를 서로 교환한다

79 현재 위치에서 L과 R의 작업을 반복한다. L은 오른쪽으로 이동하면서 피봇 보다 크거나 같은 원소인 30을 찾고, R은 왼쪽으로 이동하면서 피봇 보다 작은 원소를 찾다가 못 찾고 원소 30에서 L과 만난다. L과 R이 만났으므로 피봇과 교환하는데 R의 원소가 피봇이므로 제자리가 확정된다.

80 ⑤ 피봇 30의 왼쪽 부분 집합의 원소가 한 개 이므로 퀵 정렬을 수행하지 않고, 오른쪽 부분 집합에 대해서 퀵 정렬 수행.
오른쪽 부분 집합의 원소 2개 중에서 원소 31을 피봇으로 선택. L은 오른쪽으로 이동하면서 원소 31을 찾고, R은 왼쪽으로 이동하면서 피봇 보다 작은 원소를 찾다가 못 찾은 채로 원소 31에서 L과 만난다. L과 R이 만났으므로 피봇과 교환하는데 R의 원소가 피봇이므로 제자리가 확정된다. 피봇 31의 오른쪽 부분 집합의 원소가 한 개 이므로 퀵 정렬을 수행하지 않는다. 이것으로써 전체 퀵 정렬이 모두 완성되었다.

81 퀵 정렬 알고리즘 quickSort(a[], begin, end) if (m < n) then {
        p ← partition(a, begin, end);             quickSort(a[], begin, p-1);         quickSort(a[], p+1, end);     } end quickSort()

82 퀵 정렬 알고리즘의 분할 연산 알고리즘 partiton(a[], begin, end)
    pivot ← (begin + end)/2;     L ← begin;     R ← end;     while(L<R) do {         while(a[L]<a[pivot] and L<R) do L++;         while(a[R]≥a[pivot] and L<R) do R--;         if(L<R) then {      // L의 원소와 R의 원소 교환             temp ← a[L];                a[L] ← a[R];             a[R] ← temp;                        }     }     temp ← a[pivot];       // L의 원소와 피봇 원소 교환     a[pivot] ← a[L];     a[L] ← temp;     return L; end partition()

83 퀵 정렬 알고리즘 분석 메모리 사용공간 연산 시간 n개의 원소에 대하여 n개의 메모리 사용 최선의 경우
최악의 경우 피봇에 의해 원소들을 분할하였을 때 1개와 n-1개로 한쪽으로 치우쳐 분할되는 경우가 반복되어 수행 단계 수가 최대가 되는 경우 평균 시간 복잡도 : 𝑂(𝑛 log 2 𝑛 ) 같은 시간 복잡도를 가지는 다른 정렬 방법에 비해서 자리 교환 횟수를 줄임으로써 더 빨리 실행되어 실행 시간 성능이 좋은 정렬 방법

84 퀵 정렬 C 프로그램 정렬할 자료 : {69, 10, 30, 2, 16, 8, 31, 22} 실행 결과

85 삽입 정렬(insert sort) 정렬할 자료를 두 개의 부분집합 S와 U로 가정
정렬되어있는 부분집합에 정렬할 새로운 원소의 위치를 찾아 삽입하는 방법 정렬할 자료를 두 개의 부분집합 S와 U로 가정 부분집합 S : 정렬된 앞부분의 원소들 부분집합 U : 아직 정렬되지 않은 나머지 원소들 정렬되지 않은 부분집합 U의 원소를 하나씩 꺼내서 이미 정렬되어있는 부분집합 S의 마지막 원소부터 비교하면서 위치를 찾아 삽입 삽입 정렬을 반복하면서 부분집합 S의 원소는 하나씩 늘리고 부분집합 U의 원소는 하나씩 감소하게 한다. 부분집합 U가 공집합이 되면 삽입 정렬이 완성된다

86 삽입 정렬 수행 과정 정렬되지 않은 {69, 10, 30, 2, 16, 8, 31, 22}의 자료들을 삽입 정렬 방법으로 정렬하는 과정을 살펴보자. 초기 상태 : 첫 번째 원소는 정렬되어있는 부분 집합 S로 생각하고 나머지 원소들은 정렬되지 않은 원소들의 부분 집합 U로 생각한다. S={69}, U={10, 30, 2, 16, 8, 31, 22}

87 ① U의 첫 번째 원소 10을 S의 마지막 원소 69와 비교하여 (10 < 69) 이므로 원소 10은 원소 69의 앞자리가 된다. 더 이상 비교할 S의 원소가 없으므로 찾은 위치에 원소 10을 삽입한다.

88 ② U의 첫 번째 원소 30을 S의 마지막 원소 69와 비교하여 (30 < 69) 이므로 원소 69의 앞자리 원소 10과 비교한다.
(30 > 10) 이므로 원소 10과 69 사이에 삽입한다. 

89 ③ U의 첫 번째 원소 2를 S의 마지막 원소 69와 비교하여 (2 < 69) 이므로 원소 69의 앞자리 원소 30과 비교하고,
(2 < 30) 이므로 다시 그 앞자리 원소 10과 비교하는데,  (2 < 10) 이면서 더 이상 비교할 S의 원소가 없으므로 원소 10의 앞에 삽입한다. 

90 ④ U의 첫 번째 원소 16을 S의 마지막 원소 69와 비교하여 (16 < 69) 이므로 그 앞자리 원소 30과 비교한다.
(16 < 30) 이므로 다시 그 앞자리 원소 10과 비교하여, (16 > 10)이므로 원소 10과 30 사이에 삽입한다. 

91 ⑤ U의 첫 번째 원소 8을 S의 마지막 원소 69와 비교하여 (8 < 69) 이므로 그 앞자리 원소 30과 비교한다.
(8 < 30) 이므로 그 앞자리 원소 10과 비교하여, (8 < 10) 이므로 다시 그 앞자리 원소 2와 비교하는데, (8 > 2)이므로 원소 2와 10 사이에 삽입한다.

92 ⑥ U의 첫 번째 원소 31을 S의 마지막 원소 69와 비교하여 (31 < 69) 이므로 그 앞자리 원소 30과 비교한다.
(31 > 30) 이므로 원소 30과 69 사이에 삽입한다. 

93 ⑦ U의 첫 번째 원소 22를 S의 마지막 원소 69와 비교하여 (22 < 69) 이므로 그 앞자리 원소 31과 비교한다.
(22 < 31) 이므로 그 앞자리 원소 30과 비교하고, (22 < 30) 이므로 다시 그 앞자리 원소 16과 비교하여, (22 > 16) 이므로 원소 16과 30 사이에 삽입한다. U가 공집합이 되었으므로 실행을 종료하고 삽입 정렬이 완성된다.

94 삽입 정렬 알고리즘 insertionSort(a[],n) for (i←1; i<n; i←i+1) {
        temp ← a[i];         j ← i;         if (a[j-1]>temp) then move ← true;         else move ← false;         while (move) do {            a[j] ← a[j-1];            j ← j-1;            if (j>0 and a[j-1]>temp) then move ← true;            else move ← false;         }         a[j] ← temp;      } end insertionSort()

95 삽입 정렬 알고리즘 분석 메모리 사용공간 연산 시간 최악의 경우 : 모든 원소가 역순으로 되어있어서 비교횟수가 최대인 경우
n개의 원소에 대하여 n개의 메모리 사용 연산 시간 최선의 경우 : 원소들이 이미 정렬되어있어서 비교횟수가 최소인 경우 이미 정렬되어있는 경우에는 바로 앞자리 원소와 한번만 비교한다. 전체 비교횟수 = n-1 시간 복잡도 : O(n) 최악의 경우 : 모든 원소가 역순으로 되어있어서 비교횟수가 최대인 경우 전체 비교횟수 = ⋯ +(n-1) = n(n-1)/2 시간 복잡도 : O(n2) 삽입 정렬의 평균 비교횟수 = n(n-1)/4 평균 시간 복잡도 : O(n2)

96 최선의 경우와 최악의 경우 예 [그림 10-2] 이미 정렬되어있는 원소에서의 삽입 정렬
[그림 10-3] 역순으로 정렬되어있는 원소에서의 삽입 정렬

97 삽입 정렬 C 프로그램 정렬할 자료 : {69, 10, 30, 2, 16, 8, 31, 22} 실행 결과

98 셸 정렬(shell sort) 셸 정렬의 부분집합 셸 정렬의 성능은 매개변수 h의 값에 따라 달라진다.
일정한 간격(interval)으로 떨어져있는 자료들끼리 부분집합을 구성하고 각 부분집합에 있는 원소들에 대해서 삽입 정렬을 수행하는 작업을 반복하면서 전체 원소들을 정렬하는 방법 전체 원소에 대해서 삽입 정렬을 수행하는 것보다 부분집합으로 나누어 정렬하게 되면 비교연산과 교환연산 감소 셸 정렬의 부분집합 부분집합의 기준이 되는 간격을 매개변수 h에 저장 한 단계가 수행될 때마다 h의 값을 감소시키고 셸 정렬을 순환 호출 h가 1이 될 때까지 반복 셸 정렬의 성능은 매개변수 h의 값에 따라 달라진다. 정렬할 자료의 특성에 따라 매개변수 생성 함수를 사용 일반적으로 사용하는 h의 값은 원소 개수의 1/2을 사용하고 한 단계 수행될 때마다 h의 값을 반으로 감소시키면서 반복 수행

99 셸 정렬 수행 과정 정렬되지 않은 {69, 10, 30, 2, 16, 8, 31, 22}의 자료들을 셸 정렬 방법으로 정렬하는 과정을 살펴보자. ① 원소의 개수가 8개이므로 매개변수 h는 4에서 시작한다. h=4 이므로 간격이 4인 원소들을 같은 부분 집합으로 만들면 4개의 부분 집합이 만들어진다

100 첫 번째 부분 집합 {69, 16}에 대해서 삽입 정렬을 수행하여 정렬.
두 번째 부분 집합 {10, 8}에 대해서 삽입 정렬 수행

101 세 번째 부분 집합 {30, 31}에 대해서 삽입 정렬을 수행하는데,
(30<31) 이므로 자리 교환은 이루어지지 않는다. 네 번째 부분 집합 {2, 22}에 대해서 삽입 정렬을 수행하는데, (2<22) 이므로 자리 교환은 이루어지지 않는다

102 ② 이제 h를 2로 변경하고 다시 셸 정렬 시작. h=2 이므로 간격이 2인 원소들을 같은 부분 집합으로 만들면 2개의 부분 집합이 만들어진다. 첫 번째 부분 집합 {16, 30, 69, 31}에 대해서 삽입 정렬을 수행하여 정렬

103 두 번째 부분 집합 {8, 2, 10, 22}에 대해서 삽입 정렬을 수행하여 정렬

104 ③ 이제 h를 1로 변경하고 다시 셸 정렬 시작. h=1 이므로 간격이 1인 원소들을 같은 부분 집합으로 만들면 1개의 부분 집합이 만들어진다. 즉, 전체 원소에 대해서 삽입 정렬을 수행하고 셸 정렬이 완성된다

105 셸 정렬 알고리즘 shellSort(a[],n) interval ← n; while (interval ≥ 1) do {
        interval ← interval/2;         for (i←0; i<interval; i←i+1) do {             intervalSort(a[], i, n, interval);         }      } end shellSort()

106 셀 정렬 알고리즘 분석 메모리 사용공간 연산 시간 n개의 원소에 대하여 n개의 메모리와 매개변수 h에 대한 저장공간 사용
비교횟수 처음 원소의 상태에 상관없이 매개변수 h에 의해 결정 일반적인 시간 복잡도 : O(n1.25) 셸 정렬은 삽입 정렬의 시간 복잡도 O(n2) 보다 개선된 정렬 방법

107 셸 정렬 C 프로그램 정렬할 자료 : {69, 10, 30, 2, 16, 8, 31, 22} 실행 결과

108 병합 정렬(merge sort) 병합 정렬 방법의 종류 2-way 병합 정렬 : 세 가지 기본 작업을 반복 수행하면서 완성
여러 개의 정렬된 자료의 집합을 병합하여 한 개의 정렬된 집합으로 만드는 방법 부분집합으로 분할(divide)하고, 각 부분집합에 대해서 정렬 작업을 완성(conquer)한 후에 정렬된 부분집합들을 다시 결합(combine)하는 분할 정복(divide and conquer) 기법 사용 병합 정렬 방법의 종류 2-way 병합 : 2개의 정렬된 자료의 집합을 결합하여 하나의 집합으로 만드는 병합 방법 n-way 병합 : n개의 정렬된 자료의 집합을 결합하여 하나의 집합으로 만드는 병합 방법 2-way 병합 정렬 : 세 가지 기본 작업을 반복 수행하면서 완성 ⑴ 분할(divide) : 입력 자료를 같은 크기의 부분집합 2개로 분할한다. ⑵ 정복(conquer) : 부분집합의 원소들을 정렬한다. 부분집합의 크기가 충분히 작지 않으면 순환호출을 이용하여 다시 분할 정복 기법을 적용한다. ⑶ 결합(combine) : 정렬된 부분집합들을 하나의 집합으로 통합한다

109 병합 정렬 수행 과정 정렬되지 않은 {69, 10, 30, 2, 16, 8, 31, 22}의 자료들을 병합 정렬 방법으로 정렬하는 과정을 살펴보자. ① 분할 단계 : 정렬할 전체 자료의 집합에 대해서 최소 원소의 부분집합이 될 때까지 분할작업을 반복하여 1개의 원소를 가진 부분집합 8개를 만든다

110 ② 병합단계 : 2개의 부분집합을 정렬하면서 하나의 집합으로 병합한다. 8개의 부분집합이 1개로 병합될 때까지 반복한다

111 병합 정렬 알고리즘 메모리 사용공간 연산 시간 각 단계에서 새로 병합하여 만든 부분집합을 저장할 공간이 추가로 필요
원소 n개에 대해서 (2 x n)개의 메모리 공간 사용 연산 시간 분할 단계 : n개의 원소를 분할하기 위해서 log2n번의 단계 수행 병합 단계 : 부분집합의 원소를 비교하면서 병합하는 단계에서 최대 n번의 비교연산 수행 전체 병합 정렬의 시간 복잡도 : O(n log2n) mergeSort(a[],m,n)      if (a[m:n]의 원소수 > 1) then {         전체 집합을 두개의 부분집합으로 분할;         mergeSort(a[],m,middle);         mergeSort(a[],middle+1,n);         merge(a[m:middle],a[middle+1:n]);      } end mergeSort()

112 병합 정렬 C 프로그램 정렬할 자료 : {69, 10, 30, 2, 16, 8, 31, 22} 실행 결과

113 기수 정렬(radix sort) 원소의 키값을 나타내는 기수를 이용한 정렬 방법
정렬할 원소의 키 값에 해당하는 버킷(bucket)에 원소를 분배하였다가 버킷의 순서대로 원소를 꺼내는 방법을 반복하면서 정렬 원소의 키를 표현하는 기수만큼의 버킷 사용 예) 10진수로 표현된 키 값을 가진 원소들을 정렬할 때에는 0부터 9까지 10개의 버킷 사용 키 값의 자리수 만큼 기수 정렬을 반복 키 값의 일의 자리에 대해서 기수 정렬을 수행하고, 다음 단계에서는 키 값의 십의 자리에 대해서, 그리고 그 다음 단계에서는 백의 자리에 대해서 기수 정렬 수행 한 단계가 끝날 때마다 버킷에 분배된 원소들을 버킷의 순서대로 꺼내서 다음 단계의 기수 정렬을 수행해야 하므로 큐를 사용하여 버킷을 만든다

114 기수 정렬 수행 과정 정렬되지 않은 {69, 10, 30, 2, 16, 8, 31, 22}의 자료들을 기수 정렬로 정렬하는 과정 키 값이 두 자리 십진수 이므로, 10개의 버킷을 사용하여 기수 정렬을 두 번 반복 초기 상태 : 큐를 사용하여 0부터 9까지 10개의 버킷을 만든다

115 ① 키 값의 일의 자리에 대해서 기수 정렬 수행 정렬할 원소의 일의 자리 값에 따라서 순서대로 버킷에 분배

116 버킷에 분배된 원소들을 순서대로 꺼내서 저장하기

117 ② 키 값의 십의 자리에 대해서 기수 정렬 수행 정렬할 원소의 십의 자리 값에 따라서 순서대로 버킷에 분배

118 버킷에 분배된 원소들을 순서대로 꺼내서 저장하기

119 기수 정렬 알고리즘 radixSort(a[], n) for (k←1; k≤n; k←k+1) do {
        for (i←0; i<n; i←i+1) do  {               k번째 자릿수 값에 따라서 해당 버킷에 저장한다;               enQueue(Q[k], a[i]);             }         p← -1;         for (i←0; i≤9; i≤i+1) do  {               while (Q[i] ≠ NULL) do  {                             p←p+1;                          a[p]←deQueue(Q[i]);               }     } end radixSort()

120 기수 정렬 알고리즘 분석 메모리 사용공간 연산 시간 원소 n개에 대해서 n개의 메모리 공간 사용
기수 r에 따라 버킷 공간이 추가로 필요 연산 시간 연산 시간은 정렬할 원소의 수 n과 키 값의 자릿수 d와 버킷의 수를 결정하는 기수 r에 따라서 달라진다. 정렬할 원소 n개를 r개의 버킷에 분배하는 작업 : (n+r) 이 작업을 자릿수 d 만큼 반복 수행할 전체 작업 : d(n+r) 시간 복잡도 : O(d(n+r))

121 기수 정렬 C 프로그램 정렬할 자료 : {69, 10, 30, 2, 16, 8, 31, 22} 버킷 : 7장의 큐 프로그램 사용 실행 결과

122 히프 정렬(heap sort) 히프 정렬 수행 방법 8장의 히프 자료구조를 이용한 정렬 방법
히프에서는 항상 가장 큰 원소가 루트 노드가 되고 삭제 연산을 수행하면 항상 루트 노드의 원소를 삭제하여 반환 최대 히프에 대해서 원소의 개수만큼 삭제 연산을 수행하여 내림차순으로 정렬 수행 최소 히프에 대해서 원소의 개수만큼 삭제 연산을 수행하여 오름차순으로 정렬 수행 히프 정렬 수행 방법 ⑴ 정렬할 원소들을 입력하여 최대 히프 구성 ⑵ 히프에 대해서 삭제 연산을 수행하여 얻은 원소를 마지막 자리에 배치 ⑶ 나머지 원소에 대해서 다시 최대 히프로 재구성 원소의 개수만큼 ⑵~⑶ 을 반복 수행

123 히프 정렬 수행 과정 정렬되지 않은 {69, 10, 30, 2, 16, 8, 31, 22}의 자료들을 히프 정렬 방법으로 정렬하는 과정을 살펴보자. 초기 상태 : 정렬할 원소가 8개 이므로 노드가 8개인 완전 이진 트리를 만들고, 최대 히프로 구성한다

124 ① 히프에 삭제 연산을 수행하여 루트 노드의 원소 69를 구해서 배열의 마지막 자리에 저장
① 히프에 삭제 연산을 수행하여 루트 노드의 원소 69를 구해서 배열의 마지막 자리에 저장. 나머지 원소들에 대해서 최대 히프로 재구성

125 ② 히프에 삭제 연산을 수행하여 루트 노드의 원소 31을 구해서 배열의 비어있는 마지막 자리에 저장
② 히프에 삭제 연산을 수행하여 루트 노드의 원소 31을 구해서 배열의 비어있는 마지막 자리에 저장. 나머지 히프를 최대 히프로 재구성

126 ③ 히프에 삭제 연산을 수행하여 루트 노드의 원소 30을 구해서 배열의 비어있는 마지막 자리에 저장
③ 히프에 삭제 연산을 수행하여 루트 노드의 원소 30을 구해서 배열의 비어있는 마지막 자리에 저장. 나머지 원소들에 대해서 최대 히프로 재구성

127 ④ 히프에 삭제 연산을 수행하여 루트 노드의 원소 22를 구해서 배열의 비어있는 마지막 자리에 저장
④ 히프에 삭제 연산을 수행하여 루트 노드의 원소 22를 구해서 배열의 비어있는 마지막 자리에 저장. 나머지 원소들에 대해서 최대 히프로 재구성

128 ⑤ 히프에 삭제 연산을 수행하여 루트 노드의 원소 16을 구해서 배열의 비어있는 마지막 자리에 저장
⑤ 히프에 삭제 연산을 수행하여 루트 노드의 원소 16을 구해서 배열의 비어있는 마지막 자리에 저장. 나머지 원소들에 대해서 최대 히프로 재구성

129 ⑥ 히프에 삭제 연산을 수행하여 루트 노드의 원소 10을 구해서 배열의 비어있는 마지막 자리에 저장
⑥ 히프에 삭제 연산을 수행하여 루트 노드의 원소 10을 구해서 배열의 비어있는 마지막 자리에 저장. 나머지 원소들에 대해서 최대 히프로 재구성

130 ⑦ 히프에 삭제 연산을 수행하여 루트 노드의 원소 8을 구해서 배열의 비어있는 마지막 자리에 저장
⑦ 히프에 삭제 연산을 수행하여 루트 노드의 원소 8을 구해서 배열의 비어있는 마지막 자리에 저장. 나머지 원소들에 대해서 최대 히프로 재구성

131 ⑧ 히프에 삭제 연산을 수행하여 루트 노드의 원소 2를 구해서 배열의 비어있는 마지막 자리에 저장.
⑧ 히프에 삭제 연산을 수행하여 루트 노드의 원소 2를 구해서 배열의 비어있는 마지막 자리에 저장. 나머지 히프를 최대 히프로 재구성하는데 공백 히프가 되었으므로 히프 정렬 종료

132 히프 정렬 알고리즘 heapSort(a[]) n ← a.length-1;
    for (i←n/2; i≥1; i←i-1) do  {  //배열 a[]를 히프로 변환           makeHeap(a, i, n);                       for (i←n-1; i≥1; i←i-1) do  { //히프의 루트 노드 원소를           temp ← a[1];             // 배열의 비어있는           a[1] ← a[i+1];           // 마지막 자리에 저장           a[i+1] ← temp;           makeHeap(a, 1, i);     } end heapSort()

133 히프 정렬 알고리즘의 히프 재구성 연산 알고리즘
makeHeap(a[], h, m)     for (j←2*h; j≤m; j←2*j) do  {         if (j<m) then             if (a[j]<a[j+1]) then j ← j+1;            if (a[h]≥a[j]) then exit;         else a[j/2] ← a[j];         }     a[j/2] ← a[h]; end makeHeap()

134 히프 알고리즘 분석 메모리 사용공간 연산 시간 원소 n개에 대해서 n개의 메모리 공간 사용 크기 n의 히프 저장 공간
히프 재구성 연산 시간 n개의 노드에 대해서 완전 이진 트리는 log2(n+1)의 레벨을 가지므로 완전 이진 트리를 히프로 구성하는 평균시간은 O(log2n) n개의 노드에 대해서 n번의 히프 재구성 작업 수행 평균 시간 복잡도 : O(n log2n)

135 트리 정렬(tree sort) 트리 정렬 수행 방법 8장의 이진 탐색 트리를 이용하여 정렬하는 방법
⑴ 정렬할 원소들을 이진 탐색 트리로 구성 ⑵ 이진 탐색 트리를 중위 우선 순회 방법중위 순회 경로가 오름차순 정렬이 된다

136 트리 정렬 수행 과정 정렬되지 않은 {69, 10, 30, 2, 16, 8, 31, 22}의 자료들을 트리 정렬 방법으로 정렬하는 과정을 살펴보자. ① 원소가 8개를 차례대로 트리에 삽입하여 이진 탐색 트리 구성 ② 이진 탐색 트리를 중위 우선 순회 방법으로 순회하면서 저장

137 트리 정렬 알고리즘 트리 알고리즘 분석 treeSort(a[], n) for (i←0; i<n; i←i+1) do
메모리 사용공간 원소 n개에 대해서 n개의 메모리 공간 사용 크기 n의 이진 탐색 트리 저장 공간 연산 시간 노드 한 개에 대한 이진 탐색 트리 구성 시간 : O(log2n) n개의 노드에 대한 시간 복잡도 : O(n log2n) treeSort(a[], n)     for (i←0; i<n; i←i+1) do            insert(BST, a[i]);   // 이진 탐색 트리의 삽입 연산     inorder(BST);               // 중위 순회 연산 end treeSort()


Download ppt "C언어 응용 제 13 주 그래프2, 정렬."

Similar presentations


Ads by Google