1 / 54

자료 구조

자료 구조. 제 5 장 : 트리 이 형 원 강릉대학교 컴퓨터공학과. 학습 내용. 기본 용어 이진 트리 이진 트리의 순회 스레드 이진 트리 이진 트리의 응용 히프 이진 탐색 트리 선택 트리 포리스트 집합 표현. 기본 용어. 트리 : 1 개 이상의 노드로 이루어진 유한 집합 하나의 루트 노드 + 0 개 이상의 서브 트리들  서브 트리는 서로 연결될 수 없음 트리의 각 원소는 어떤 서브 트리의 루트가 됨

zariel
Télécharger la présentation

자료 구조

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 자료 구조 제 5 장 : 트리 이 형 원 강릉대학교 컴퓨터공학과

  2. 학습 내용 • 기본 용어 • 이진 트리 • 이진 트리의 순회 • 스레드 이진 트리 • 이진 트리의 응용 • 히프 • 이진 탐색 트리 • 선택 트리 • 포리스트 • 집합 표현

  3. 기본 용어 • 트리 : 1개 이상의 노드로 이루어진 유한 집합 하나의 루트 노드 + 0개 이상의 서브 트리들  서브 트리는 서로 연결될 수 없음 트리의 각 원소는 어떤 서브 트리의 루트가 됨 • 노드 : 정보 항목 + 가지(edge) • 노드의 차수(degree) : 해당 노드에 대한 서브 트리 수 • 리프(leaf) 노드, 단말(terminal) 노드 : 차수가 0인 노드 • 비단말(non-terminal) 노드 • 부모(parent) , 자식(children), 형제(sibling) • 조상 : 루트에서 해당 노드까지의 경로상에 있는 노드들 • 자손 : 한 노드의 서브 트리에 속한 모든 노드들 • 노드 레벨(level) : 부모의 노드 레벨 + 1(루트의 레벨은 1) • 트리 높이(height)/깊이(depth) : 최대 노드 레벨

  4. I A B C D G F E K H M L 트리의 예 레벨 루트(차수=3) 1 노드 G의 조상 2 부모 자식 자식 J 3 단말 형제 형제 4 트리 높이 노드 D의 자손

  5. 트리의 표현 • 리스트 표현 • 노드 구조 : 데이터 링크 1 링크 2 ..… 링크 n • 왼쪽 자식-오른쪽 형제 표현 • 일정 크기의 노드를 다루는 것이 편리 • 노드 구조 : 데이터 왼쪽 자식 오른쪽 형제 • 일반적인 트리에서는 자식의 순서는 중요하지 않음 • 차수가 2인 트리 (왼쪽 자식-오른쪽 자식) 표현 • 왼쪽 자식-오른쪽 형제 트리를 45도 시계방향으로 비틈

  6. J J I I A B C D G F E H M L A L B C D G F E H M K K 트리의 표현(계속)

  7. 이진 트리: ADT • structure Binary_Tree objects: 공백이거나 (루트 노드, 왼쪽 Binary_Tree, 오른쪽 Binary_Tree)로 구성되는 노드들의 유한집합 functions: 모든 bt, bt1, bt2 ∈ BinTree, item ∈ element BinTree Create() ::= 공백 이진 트리를 생성Boolean IsEmpty(bt) ::= if (bt == 공백 이진 트리) return TRUE else return FALSEBinTree MakeBT(bt1, item, bt2) ::= 왼쪽 서브 트리가 bt1, 오른쪽 서브 트리가 bt2, 루트는 데이타를 갖는 이진 트리를 반환BinTree Lchild(bt) ::= if (IsEmpty(bt)) return 에러else bt의 왼쪽 서브 트리를 반환element Data(bt) ::= if (IsEmpty(bt)) return 에러else bt의 루트에 있는 데이타를 반환BinTree Rchild(bt) ::= if (IsEmpty(bt)) return 에러else bt의 오른쪽 서브 트리를 반환

  8. I A B C D E A B C D G F E H 이진 트리: 개요 • 어떤 트리도 이진(binary) 트리로 표현할 수 있음 리스트 표현  왼쪽 자식-오른쪽 형제 표현  왼쪽 자식-오른쪽 자식 표현 • 일반 트리와의 차이점 ① 노드의 차수가 2이하 ② 이진 트리는 공백 트리 가능 ③ 이진 트리는 자식의 순서를 구분 • 특수 이진 트리 • 경사(skewed) 트리 • 완전(complete) 이진 트리

  9. 9 6 7 4 8 2 1 5 3 13 12 11 15 14 10 이진 트리: 개요(계속) • 특성 • 이진 트리의 레벨 i에서의 최대 노드 수 = 2i-1 (i≥1) • 깊이가 k인 이진 트리의 최대 노드 수 = 2k - 1 (k≥1) • 단말 노드 수 = 차수가 2인 노드 수 + 1 • 포화(full) 이진 트리: 트리의 깊이가 k일 때 노드 수가 2k - 1

  10. 이진 트리: 배열 표현 • 일차원 배열에 그림 5.10의 번호 할당 기법에 의해 저장 • 배열의 0번째 원소는 사용하지 않음 • n 개의 노드를 가진 완전 이진 트리의 경우 ① if (i≠ 1) parent(i)는 i/2 의 위치, o.w. 부모가 없다 ② if (2i≤n) left_child(i)는 2i의 위치, o.w. i의 왼쪽 자식이 없다 ③ if(2i+1≤n) right_child(i)는 2i+1의 위치, o.w. i의 오른쪽 자식이 없다 • 삽입/삭제가 없는 완전 이진 트리에 적합 [1] [2] [3] [4] [5] [6] [7] [8] [9] ….. [16] A B C D ….. E 경사 트리 [1] [2] [3] [4] [5] [6] [7] [8] [9] A B C D E F G H I 완전 이진 트리

  11. 이진 트리: 링크 표현 • 노드 구조: left_child data right_child ↓ ↓ root of left subtree root of right subtree • C 언어 정의 typedef struct node *tree-pointer;typedef struct node { int data; tree_pointer left_child, right_child;}; • 단점 • difficult to find parent : Q. How to solve ? • too many null pointers : Q. How many ?

  12. C + * E * / D A B 이진 트리: 순회 • 트리 순회(traversal) • 트리에 있는 모든 노드를 한번씩 방문 • 노드와 서브 트리를 같은 방법으로 처리하는 것이 효율적 • L : 왼쪽으로 이동, V : 노드 방문, R : 오른쪽으로 이동 예제 트리 A/B*C*D+E

  13. 이진 트리: 중위 순회 • 방법 : LVR void inorder(tree_pointer ptr) { if (ptr) { inorder(ptr->left_child); /* traverse left subtree in inorder */ printf("%d", ptr->data); /* visit */ inorder(ptr->right_child); /* traverse right subtree in inorder */ } } • 순회 결과 :A / B * C * D + E

  14. 이진 트리: 전위 순회 • 방법 : VLR void preorder(tree_pointer ptr) { if (ptr) { printf("%d", ptr->data); /* visit */ preorder(ptr->left_child); /* traverse left subtree in preorder */ preorder(ptr->right_child); /* traverse right subtree in preorder */ } } • 순회 결과 : + * * / A B C D E

  15. 이진 트리: 후위 순회 • 방법 : LRV void postorder(tree_pointer ptr) { if (ptr) { postorder(ptr->left_child); /* traverse left subtree in postorder */ postorder(ptr->right_child); /* traverse right subtree in postorder */ printf("%d", ptr->data); /* visit */ } } • 순회 결과 : A B / C * D * E +

  16. 이진 트리: 반복적 중위 순회 • 방법 : 순환을 simulate하기 위한 스택 필요 void iter_inorder(tree_pointer node) { int top = -1; tree_pointer stack[MAX_STACK_SIZE]; for (;;) { for (; node; node = node->left_child) add(&top, node); node = delete(&top); if (!node) break; /* 공백 스택 */ printf("%d", node->data); node = node->right_child; }} Q. 시간 복잡도 ?

  17. 이진 트리: 레벨 순서 순회 • 루트로부터 단말 노드까지 차례대로 순회 : 큐를 사용 void level_order(tree_pointer ptr) { int front = rear = 0; tree_pointer queue[MAX_QUEUE_SIZE]; if (!ptr) return; /* 공백 트리 */ addq(front, &rear, ptr); for (;;) { ptr = deleteq(&front, rear); if (ptr) { printf("%d", ptr->data); if(ptr->left_child) addq(front, &rear, ptr->left_child); if (ptr->right_child) addq(front, &rear, ptr->right_child); } else break; }} • 순회 결과 : + * E * D / C A B

  18. 이진 트리: 복사 • 후위 순회 함수를 변경 tree_pointer copy(tree_pointer original) { /*복사된 트리의 tree_pointer 반환 */ tree_pointer temp; if (original) { temp = (tree_pointer) malloc(sizeof(node)); if (IS_FULL(temp)) { fprintf(stderr, "The memory is full"); exit(1); } temp->left_child = copy(original->left_child); temp->right_child = copy(original->right_child); temp->data = original->data; return temp; } return NULL;}

  19. 이진 트리: 동일성 검사 • 전위 순회 함수를 변경 int equal(tree_pointer first, tree_pointer second) /* 두 이진 트리가 같으면 TRUE, 그렇지 않으면 FALSE 반환 */ { return ((!first && !second) || (first && second && (first->data == second->data) && equal(first->left_child, second->left_child) && equal(first->right_child, second->right_child)); }

  20. ∨ ∨ ┐ ∧ ∧ ┐ x3 x3 x1 x2 x1 이진 트리: 만족성 문제 • 명제식의 값이 참이 되도록 할 수 있는가 변수 x1, .., xn과 연산자 ∧(and), ∨(or), ┐(not)으로 이루어진 식 • Ο(g2n) : g는 변수에 값을 대입 & 식을 계산하는 시간 • 예: (x1∧┐x2)∨(┐x1∧x3)∨┐x3에 대한 이진 트리 중위 순회 결과 x1∧┐x2∨┐x1∧x3∨┐x3

  21. 이진 트리: 만족성 문제(계속) • 방법 • 트리를 후위 순회 • 노드 방문 시 두 서브 트리의 값을 이용하여 계산 • 노드 구조 typedef enum {not, and, or, true, false} logical; typedef struct node *tree_pointer; typedef struct node { tree_pointer left_child; logical data; /* 변수 값 또는 연산자 */ short int value; /* T/F */ tree_pointer right_child; } ; • 리프 노드의 node->data는 이 노드가 나타내는 변수의 현재 값을 갖는다고 가정

  22. 이진 트리: 만족성 문제(계속) • 초기 알고리즘 for (all 2n possible combinations) { generate the next combination; replace the variables by their values; evaluate root by traversing it in postorder; if (root->value) { printf(<combination>); return; } } printf("No satisfiable combination");

  23. 이진 트리: 만족성 문제(계속) void post_order_eval(tree_pointer node) {if (node) { post_order_eval(node->left_child); post_order_eval(node->right_child); switch (node->data) { case not : node->value = !node->right_child->value; break; case and: node->value=node->right_child->value && node->left_child->value; break; case or: node->value = node->right_child->value || node->left_child->value; break; case true: node->value = TRUE; break; case false: node->value = FALSE; }} }

  24. I A B C D G F E H 스레드(threaded) 이진 트리 • 스레드 • null link를 다른 노드를 가리키는 ptr인 스레드로 대치 • 스레드 구성의 규칙 ptr->left_child가 널이면 ptr->left_child=ptr의 중위 선행자로의 포인터 ptr->right_child가 널이면 ptr->right_child=ptr의 중위 후속자로의 포인터 root 중위 순회 H D I B E A F C G

  25. 스레드 이진 트리: 노드 구조 • 스레드와 정상적인 포인터를 구별 left_thread left_child data right_child right_thread left_thread가 T이면, left_child : thread o.w. left_child : normal pointer right_thread가 T이면, right_child : thread o.w. right_child : normal pointer typedef struct threaded_tree *thread_pointer;typedef struct threaded_tree { short int left_thread, right_thread; threaded_pointer left_child, right_child; char data;}; • 분실 스레드 : 헤드 노드로 해결

  26. f • A • f f • B • f f • – • f f • C • f f • D • f t • I • t t • F • t t • G • t t • H • t t • E • t 스레드 이진 트리: 예 left_thread left_child data right_child right_thread _ TRUE FALSE ° ° root

  27. 스레드 이진 트리: 중위 순회 threaded_pointer insucc(threaded_pointer tree) { /* 중위 후속자를 찾는다. */ threaded_pointer temp; temp = tree->right_child; if (!tree->right_thread) while (!temp->left_thread) temp = temp->left_child; return temp;} void tinorder(threaded_pointer tree) {/* 스레드 이진 트리의 중위 순회 */ threaded_pointer temp = tree; for (;;) { temp = insucc(temp); if (temp = tree) break; printf("%3c", temp->data); }} Q. 시간 복잡도 ? Q. 전위 및 후위 순회 ?

  28. C C A A B D B D 스레드 이진 트리: 노드 삽입 • 노드 child를 노드 parent의 오른쪽 자식으로 삽입 ⑴ parent의 오른쪽 subtree가 공백인 경우  child->right_child = parent->right_child, child->right_thread = TRUE  child->left_child = parent, child->left_thread = TRUE  parent->right_child = child, parent->right_thread = FALSE  parent   child

  29. C C E E A F D D F A X X B B 스레드 이진 트리: 노드 삽입(계속) ⑵ parent의 오른쪽 subtree가 공백이 아닌 경우  child->right_child = parent->right_child, child->right_thread = FALSE  child->left_child = parent , child->left_thread = TRUE  parent->right_child = child, parent->right_thread = FALSE  insucc(child)->left_child = child parent     child

  30. 스레드 이진 트리: 노드 삽입(계속) void insert_right(threaded_pointer parent, threaded_pointer child) {/* 스레드 이진 트리에서 child를 parent의 오른쪽 자식으로 삽입 */ threaded_pointer temp; child->right_child = parent->right_child; /*  - 1 */ child->right_thread = parent->right_thread; /*  - 2 */ child->left_child = parent; child->left_thread = TRUE; /*  */ parent->right_child = child; parent->right_thread = FALSE; /*  */ if (!child->right_thread) { /*  */ temp = insucc(child); temp->left_child = child; }}

  31. 14 2 7 4 12 7 10 10 8 8 6 6 히프(heap): 정의 • 최대 히프와 최소 히프 • 최대 트리 : 각 노드의 키 값이 자식의 키 값보다 작지 않은 트리 • 최대 히프 : 최대 트리인 완전 이진 트리 (루트 : 가장 큰 키 값) • 최소 트리 : 각 노드의 키 값이 자식의 키 값보다 크지 않은 트리 • 최소 히프 : 최소 트리인 완전 이진 트리 (루트 : 가장 작은 키 값) • 히프의 표현 : 배열 Q. Why ? [1] [1] [2] [3] [2] [3] [4] [5] [6] [4] [5] [6]

  32. 히프(heap): 최대 히프 ADT structure MaxHeap objects : 각 노드의 값이 그 자식들보다 작지 않은 완전 이진 트리 functions : heap ∈ MaxHeap, item ∈ Element, n, max_size ∈ integer MaxHeap Create(max_size) ::= 최대 max_size개의 원소를 갖는 공백 히프를 생성Boolean HeapFull(heap, n) ::= if (n == max_size) return TRUE else return FALSEMaxHeap Insert(heap, item, n) ::= if (!HeapFull(heap, n)) item을 삽입하고 그 히프를 반환 else return 에러Boolean HeapEmpty(heap, n) ::= if (n>0) return TRUE else return FALSEElement Delete(heap, n) ::= if (!HeapEmpty(heap, n)) 히프의 가장 큰 원소를 제거하고 반환else return 에러

  33. 히프: 우선 순위 큐 • 우선 순위 큐 • 우선 순위가 가장 높은(낮은) 원소를 먼저 삭제하는 큐 예) OS의 작업 스케쥴러 • 우선 순위 큐의 표현 방법 표현 방법 삽입 삭제 순서없는 배열 Θ(1) Θ(n) 순서없는 연결 리스트 Θ(1) Θ(n) 정렬된 배열 O(n) Θ(1) 정렬된 연결 리스트 O(n) Θ(1) 최대 히프 O(log2n) O(log2n)

  34. 21 20 20 20 2 2 15 15 15 10 10 2 10 14 14 14 히프: 최대 히프에서의 삽입 • 방법 • 완전이진 트리를 유지 : 삽입 위치는 일정 • 최대 트리의 유지 : 한 원소에서 부모를 찾아갈 수 있어야 함  연결 리스트 사용 : 부모 필드 첨가배열 사용 : 추가 필드없이 부모 찾기가 용이 [1] [1] [1] [2] [3] [2] [3] [2] [3] [4] [5] [4] [5] [4] [5] [6] [6]

  35. 히프: 최대 히프에서의 삽입(계속) #define MAX_ELEMENTS 200 /* 최대 히프 크기 + 1 */#define HEAP_FULL(n) (n == MAX_ELEMENTS-1)#define HEAP_EMPTY(n) (!n)typedef struct { int key; …. /* 다른 필드들 */ } element;element heap[MAX_ELEMENTS];int n = 0;void insert_max_heap(element item, int *n) { /* n개의 원소를 갖는 최대 히프에 item을 삽입한다. */ int i; if (HEAP_FULL(*n)) { fprintf(stderr, "The heap is full.\n"); exit(1); } i = ++(*n); while ((i != 1) && (item.key > heap[i/2].key)) { heap[i] = heap[i/2]; i /= 2; } heap[i] = item;} Q. 시간 복잡도 ?

  36. 10 20 15 2 2 2 2 15 14 15 15 10 10 14 10 14 14 히프: 최대 히프에서의 삭제 • 방법 • 항상 히프의 루트에서 삭제 • 완전 이진 트리 및 최대 트리를 만족하도록 재구성 [1] [1] [1] [1] [2] [3] [2] [3] [2] [3] [2] [3] [4] [5] [4] [5] [4] [4]

  37. 히프: 최대 히프에서의 삭제(계속) element delete_max_heap(int *n) { /* 가장 큰 값의 원소를 히프에서 삭제 */ int parent, child; element item, temp; if (HEAP_EMPTY(*n)) { fprintf(stderr, "The heap is empty"); exit(1); } item = heap[1]; /* 가장 큰 키값을 저장 */ /* 히프를 재구성하기위해 마지막 원소를 이용 */ temp = heap[(*n)--]; parent = 1; child = 2; while (child <= *n) { /* 현 parent의 가장 큰 자식을 탐색 */ if ((child < *n) && (heap[child].key) < heap[child+1].key)) child++; if (temp.key >= heap[child].key) break; /* 아래 단계로 이동 */ heap[parent] = heap[child]; parent = child; child *= 2; } heap [parent] = temp; return item;} Q. 시간 복잡도 ?

  38. 20 30 60 15 5 10 22 80 25 40 70 12 2 65 이진 탐색 트리: 개요 • 이진 탐색 트리 • 임의의 원소 탐색/삽입/삭제에 적합 Q. 히프 ? • 정의 • 모든 원소는 유일한 값의 키를 가짐 • 왼쪽 서브트리 키 < 그 서브트리의 루트 키 < 오른쪽 서브트리 키 • 왼쪽과 오른쪽 서브 트리도 이진 탐색 트리 • 이진 트리의 하나 : C 선언 및 기존 연산이 모두 적용

  39. 이진 탐색 트리: 탐색 • 순환 탐색과 반복 탐색 Q. 시간 복잡도 ?tree_pointer search(tree_pointer root, int key) { if (!root) return NULL; if (key == root->data) return root; if (key < root->data) return search(root->left_child, key); return search(root->right_child, key);}tree_pointer search2(tree_pointer tree, int key) { while (tree) { if (key == tree->data) return tree; if (key < tree->data) tree = tree->left_child; else tree = tree->right_child; } return NULL;}

  40. 30 30 30 5 5 5 40 40 40 2 35 2 80 2 80 이진 탐색 트리: 삽입 • 방법  동일한 키 값을 갖는 원소가 존재하는지 확인하기 위해 탐색  탐색이 실패하면 탐색이 종료된 지점에 원소 삽입

  41. 이진 탐색 트리: 삽입(계속) void insert_node(tree_pointer *node, int num) { /* 트리내의 노드가 num을 가리키고 있으면 아무 일도 하지 않음; 그렇지 않은 경우는 data=num인 새 노드를 첨가 */ tree_pointer ptr, temp = modified_search(*node, num); if (temp || !(*node)) { /* num이 트리내에 없음 */ ptr = (tree_pointer)malloc(sizeof(node)) ; if (IS_FULL(ptr)) {fprintf(stderr, "The memory is full"); exit(1); } ptr->data = num; ptr->left_child = ptr->right_child = NULL; if (*node) /* temp의 자식으로 삽입 */ if (num < temp->data) temp->left_child = ptr; else temp->right_child = ptr; else *node = ptr: }} Q. 시간 복잡도 ?

  42. 30 30 30 5 5 5 80 40 40 35 80 2 80 2 2 이진 탐색 트리: 삭제 • 삭제 노드의 형태 ① 리프 노드 L L 삭제 L의 부모 노드의 자식 필드를 NULL ② 하나의 자식을 갖는 비단말 노드 S S 삭제 S의 자식을 삭제된 노드의 자리에 위치

  43. 60 55 40 40 20 20 50 50 10 70 30 55 45 70 52 10 30 45 52 이진 탐색 트리: 삭제(계속) ③ 두개의 자식을 갖는 비단말 노드 D D를 (left subtree의 largest 노드 or right subtree의 smallest 노드)로 대체 선택된 subtree에서 치환된 원소(항상 차수가 0 또는 1)의 삭제 Q. 알고리즘의 복잡도 ? 삭제 노드

  44. 이진 탐색 트리: 높이 • n개의 원소를 갖는 이진 탐색 트리의 높이 • 최악의 경우 n : 함수 insert_node를 이용하여 1,2,...,n을 삽입 • 평균적으로 Ο(log2 n) : 삽입과 삭제가 random • 균형 탐색 트리 • 최악의 경우에도 높이가Ο(log2 n)인 탐색 트리 • 예 : AVL 트리,2-3 트리, 레드-블랙 트리 • 탐색, 삽입, 삭제가 Ο(h)

  45. 선택 트리 • 문제 • K 개의 순서 순차를 하나의 순서 순차(비감소)로 합병 • 가정 • 각 순차(런)는 키 필드에 따라 비감소 순서로 정렬된 레코드들로 구성 • k개의 런에 있는 레코드의 총 수는 n • 방법 1 for ( i=1; i<= n; i++) { k개의 런의 첫번째 레코드들 중 가장 작은 키 값의 레코드를 선택 해당 레코드를 출력 해당 레코드가 속해 있는 런에서 그 레코드를 삭제 } Q. 시간 복잡도 ?

  46. 선택 트리(계속) • 방법 2 : 선택 트리 사용 • 선택 트리 • 각 노드가 두 개의 자식 노드 중 더 작은 노드를 표현하는 이진 트리 • 더 작은 키 값을 갖는 레코드가 승자가 되는 토너먼트와 동일 • 각 노드는 그 노드를 표현하는 레코드에 대한 포인터만 포함 : 배열 사용 • 토너먼트는 형제 노드간 시행, 결과는 부모 노드에 위치 • 배열 표현이므로 형제, 부모 노드의 주소 계산이 효율적 • 알고리즘 선택 트리 초기화 for ( i=1; i<= n; i++) 루트 노드를 출력하고 선택 트리를 재구성 • 시간 복잡도 : Ο(n log2 k)

  47. 100110… 100110… 8 6 8 6 9 8 8 9 8 9 90 9 15 20 17 9 90 17 9 6 9 20 15 6 17 17 1516… 1550… 2030… 1116… 1525… 2038… 2530… 1820… 1550… 2038… 1516… 2030… 1116… 1820… 런7 런7 10 8 8 10 런5 런3 런4 런2 런1 런8 런8 런6 런5 런4 런3 런2 런1 런6 선택 트리(계속) 1 1 2 2 3 3 6 7 6 7 4 5 4 5 8 8 9 10 11 12 13 14 15 9 10 11 12 13 14 15

  48. G A E E G A B H H B D I D I F C C F 포리스트 • n≥0개의 트리들의 집합 (트리의 루트 제거) • 포리스트의 이진 트리 변환 방법 • 포리스트의 각 트리를 이진 트리로 변환 • 첫 번째 트리의 루트로부터 오른쪽 서브 트리를 따라 나머지 트리들의 루트들을 차례대로 연결

  49. 0 4 2 6 1 3 8 9 5 7 집합 표현 • 개요 • 집합의 원소는 0,1,...,n-1 등의 수 • 모든 집합들은 서로 분리(disjoint) 관계 • 집합의 포리스트 표현 (링크의 방향 주의) S1 = {0, 6, 7, 8}, S2 = {1, 4, 9}, S3= {2, 3, 5} • 수행 연산 ⑴ Union(i,j) : SiU Sj ⑵ Find(i) : 원소 i가 포함된 집합 찾기 S1 S2 S3

  50. 집합 포인터 이름 S1 S2 S3 4 0 4 0 2 1 6 3 1 6 9 8 5 8 9 7 7 집합 표현(계속) • union 연산 • 트리를 다른 트리의 서브 트리로 • 구현: 한 루트의 부모 필드가 다른 트리의 루트를 가리키게 함 • find 연산 • 각 루트가 집합 이름에 대한 포인터를 갖게 함 • 구현: 루트로 연결된 부모 링크를 따라 올라가서 집합 이름을 가리키는 포인터를 찾음 • 편의상, 트리의 루트를 집합이름으로 사용 S1 U S2

More Related