1 / 41

5. 스택과 스레드 이진트리

5. 스택과 스레드 이진트리. 스택에 의한 전위순회  Depth First Search. IterativePreorder (Nptr p) { S.create( ); if (p != NULL) { S.Push(p); while (! S.IsEmpty( )) { p = S.Pop( ); Visit(p); if (p->RChild != NULL) S.Push(p->RChild);  if (p->LChild != NULL) S.Push(p->LChild);   } } }.

cher
Download Presentation

5. 스택과 스레드 이진트리

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. 스택과 스레드 이진트리 • 스택에 의한 전위순회 Depth First Search IterativePreorder (Nptr p) { S.create( ); if (p != NULL) { S.Push(p); while (! S.IsEmpty( )) { p = S.Pop( ); Visit(p); if (p->RChild != NULL)S.Push(p->RChild);  if (p->LChild != NULL) S.Push(p->LChild);   } } } 이전 PPT의 22페이지와 비교 순서 주의 방문 순서: G, C, A, E, L Data Structure

  2. 5. 스택과 스레드 이진트리 • 스택사용 • 재귀호출을 이용한 시스템 스택이건 사용자 스택이건 스택 공간과 함께, 푸쉬 팝을 위한 실행시간이 요구됨. • 스택의 사용을 완전히 배제함으로써 효율성을 추구할 수는 없는가. • 해결책: 스레드 트리 (Thread Tree) • 노드마다 추가로 선행자 (Predecessor)와 후속자 (Successor) 포인터 추가 • 이러한 포인터를 스레드(실, Thread)라 함. • 메모리 공간면에서는 비효율적 typedef struct { char Name[ ];        이름 필드 node* LChild;          왼쪽 자식을 가리키는 포인터 node* RChild;          오른쪽 자식을 가리키는 포인터 node* Predecessor;선행자 node* Successor;후속자 } node;                  노드는 구조체 타입 typedef node* Nptr;  노드를 가리키는 포인터를 Nptr 타입으로 정함 Data Structure

  3. 5. 스택과 스레드 이진트리 • 중위순회를 위한 쓰레드 트리 (Thread Tree) • 순회를 위해서 실제로는 후속자 (Successor) 만 사용됨 • Rchild가 널일 경우만 중위순회 후속자가 필요. • 따라서 후속자 (Successor) 필드 없이 Rchild 필드를 스레드로 대용 가능. • 재귀호출이나 사용자 스택 없이 중위순회 방문 순서: Q, G, C, T, F, K, A, E, D, B Data Structure

  4. 5. 스택과 스레드 이진트리 • 스레드에 의한 중위순회 Pseudo Code typedef struct { char Name[ ]; node* LChild; node* RChild; bool IsThread; } node; typedef node* Nptr; Nptr nodeA; Nptr nodeB; Nptr nodeC; Nptr nodeG; Nptr nodeF; Nptr nodeQ; … … void configNode(Nptr n, char[] nm, Nptr lt, Nptr rt, bool isTd) { n->Name = nm; n->LChild = lt; n->RChild = rt; n->IsThread = isTd; } configNode(nodeA, “A”, nodeC, nodeB, false); configNode(nodeC, “C”, nodeG, nodeF, false); configNode(nodeG, “G”, nodeQ, nodeC, true); configNode(nodeQ, “Q”, null, nodeG, true); Data Structure

  5. 5. 스택과 스레드 이진트리 Threaded Tree Traversal – Inorder (중위순회) Output 1 6 8 3 1 5 7 11 9 13 Start at leftmost node, print it Data Structure

  6. 5. 스택과 스레드 이진트리 Threaded Tree Traversal – Inorder (중위순회) Output 1 3 6 8 3 1 5 7 11 9 13 Follow thread to right, print node Data Structure

  7. 5. 스택과 스레드 이진트리 Threaded Tree Traversal – Inorder (중위순회) Output 1 3 5 6 8 3 1 5 7 11 9 13 Follow link to right, go to leftmost node and print Data Structure

  8. 5. 스택과 스레드 이진트리 Threaded Tree Traversal – Inorder (중위순회) Output 1 3 5 6 6 8 3 1 5 7 11 9 13 Follow thread to right, print node Data Structure

  9. 5. 스택과 스레드 이진트리 Threaded Tree Traversal – Inorder (중위순회) Output 1 3 5 6 7 6 8 3 1 5 7 11 9 13 Follow link to right, go to leftmost node and print Data Structure

  10. 5. 스택과 스레드 이진트리 Threaded Tree Traversal – Inorder (중위순회) Output 1 3 5 6 7 8 6 8 3 1 5 7 11 9 13 Follow thread to right, print node Data Structure

  11. 5. 스택과 스레드 이진트리 Threaded Tree Traversal – Inorder (중위순회) Output 1 3 5 6 7 8 9 6 8 3 1 5 7 11 9 13 Follow link to right, go to leftmost node and print Data Structure

  12. 5. 스택과 스레드 이진트리 Threaded Tree Traversal – Inorder (중위순회) Output 1 3 5 6 7 8 9 11 6 8 3 1 5 7 11 9 13 Follow thread to right, print node Data Structure

  13. 5. 스택과 스레드 이진트리 Threaded Tree Traversal – Inorder (중위순회) Output 1 3 5 6 7 8 9 11 13 6 8 3 1 5 7 11 9 13 Follow link to right, go to leftmost node and print Data Structure

  14. 5. 스택과 스레드 이진트리 • 스레드에 의한 중위순회 Pseudo Code ThreadInorder (Nptr p) { if (p != NULL) { while (p->LChild != NULL)          p = p->LChild;           트리의 가장 왼쪽 자식으로 while (p != NULL) {          Visit(p);                     일단 방문하고 Nptr Prev = p;                   현재 노드를 Prev에 저장 p = p->RChild;  오른쪽 자식노드 또는 중위후속자로 이동 if (p != NULL && Prev->IsThread = = FALSE) 오른쪽 자식노드라면 while (p->LChild != NULL)              다시 가장 왼쪽 자식으로 p = p->LChild;         }     } } Data Structure

  15. 5. 스택과 스레드 이진트리 • 전위순회(Preorder)를 위한 쓰레드 트리 (Thread Tree) • LChild 필드를 스레드로 대용. typedef struct { char Name[ ];        node* LChild;          node* RChild;          bool IsThread; //이진 트리의 구조 유지위해 필요 } node;                  typedef node* Nptr;  ThreadInorder2 (Nptr p) { if (p != NULL) { Visit(p); p = p-> LChild;          }     } } Data Structure

  16. 6. 이진트리의 복사 • 이진트리 T를 복사하고, 복사된 트리의 루트노드를 가리키는 포인터를 돌려주는 함수 • 아래 방법은 재귀와 전위순회를 활용하고 있음 Nptr CopyTree(Nptr T) {  T는 원본의 루트 포인터 if (T = = NULL)            원본 포인터가 가리키는 노드가 더 이상 없다면 return NULL;             복사할 노드 포인터도 널로 세팅 else {                               원본 포인터에 매달린 노드가 있다면 Nptr T1 = (node *)malloc(sizeof(node));  새로운 노드를 만들고 T1->Name = T->Name;                데이터를 복사한다.       T1->LChild = CopyTree(T->LChild);   서브트리의 루트 포인터를 할당 T1->RChild = CopyTree(T->RChild);   서브트리의 루트 포인터를 할당 return T1;                              서브트리의 루트 포인터를 리턴 }   } Data Structure

  17. 7. 이진 탐색 트리 • Binary Search Tree (이진 탐색 트리) • [정의] 모든 노드 N에 대하여, • N의 왼쪽 서브트리에 있는 모든 노드는 N보다 작고, N의 오른쪽 서브트리에 있는 모든 노드는 N보다 크다 • N의 왼쪽 서브트리와 N의 오른쪽 서브트리도 이진 탐색 트리다. • 노드 위치는 키 값을 기준으로 결정. • 탐색에 유리. Data Structure

  18. 7. 이진 탐색 트리 • Binary Search Tree (이진 탐색 트리) • 이진 탐색 트리는 “약하게 정렬되어 있다”라고 함 • “어느정도는 정렬이 되어 있다.” • 루트를 중심으로 왼쪽 서브트리는 작은 것, 오른쪽 서브트리는 큰 것 • 쾌속정렬의 파티션과 유사. 루트 노드는 일종의 피벗에 해당 • 피벗(Pivot)을 중심으로 작은 것은 모두 왼쪽, 큰 것은 모두 오른쪽 • 서브트리만 놓고 볼 때도 다시 파티션 된 상태이다 Data Structure

  19. 7. 이진 탐색 트리 • Binary Search Tree (이진 탐색 트리) • A data structure for efficient searching, insertion and deletion • Binary search tree property • For every node X • All the keys in its left subtree are smaller than the key value in X • All the keys in its right subtree are larger than the key value in X Data Structure

  20. 7. 이진 탐색 트리 • Binary Search Tree (이진 탐색 트리) Not a binary search tree A binary search tree Data Structure

  21. 7. 이진 탐색 트리 • Binary Search Tree (이진 탐색 트리) • Average depth of a node is O(log N) • Maximum depth of a node is O(N) The same set of keys may have different BSTs Data Structure

  22. 7. 이진 탐색 트리 • 교재에서활용되는 이진 트리 (Binary Tree)의 선언 • 아래에서 학번이 Key Field로 이용될 때 접근 법 • 노드 변수 Node1의 타입이 node일 때: Node1.Data.Key • 노드 변수 Node1의 타입이 Nptr일 때: Node1Data.key typedef struct { int Key;               학번   char Name[12];       성명   char Address[200]   주소 } dataType; typedef struct { dataType Data;       데이터는 하나의 구조체 node* LChild;          왼쪽 자식을 가리키는 포인터   node* RChild;          오른쪽 자식을 가리키는 포인터 } node;                  구조체 타입 노드 typedef node* Nptr; Data Structure

  23. 7. 이진 탐색 트리 • Binary Search Tree (이진 탐색 트리)의 탐색 (Search) • If we are searching for 15, then we are done. • If we are searching for a key < 15, then we should search in the left subtree. • If we are searching for a key > 15, then we should search in the right subtree. Data Structure

  24. 7. 이진 탐색 트리 • Binary Search Tree (이진 탐색 트리)의 탐색 (Search) Data Structure

  25. 7. 이진 탐색 트리 • Binary Search Tree (이진 탐색 트리)의 탐색 (Search) Nptr Search(Nptr T, int Key) { if (T = = NULL)           printf("No Such Node");               오류 처리 후 빠져나옴 else if (T->Data.Key = = Key)           return T;                             찾아낸 노드 포인터를 리턴 else if (T->Data.Key > Key)           return Search(T->LChild, Key);  else           return Search(T->RChild, Key);    } Data Structure

  26. 7. 이진 탐색 트리 • Binary Search Tree (이진 탐색 트리)의 삽입 • 삽일 할 새로운 노드는 Leaf Node로서 들어감 • 즉, 삽입 위치는 현재 NULL인 곳임 Data Structure

  27. 7. 이진 탐색 트리 • Binary Search Tree (이진 탐색 트리)의 삽입 Nptr Insert(Nptr T, int Key) { if (T = = NULL) {                          리프노드의 Child 포인터 T = (node*)malloc(sizeof(node));     삽입할 새 노드를 만들기 T->Data.Key = Key;                  필요시 나머지 데이터 필드 복사 T->LChild = NULL; T->RChild = NULL; 리프노드이므로 자식노드를 널로 } else if (T->Data.Key > Key)                      T->LChild = Insert(T->LChild, Key); 왼쪽 서브트리로 재귀호출 else                                         T->RChild = Insert(T->RChild, Key); 오른쪽 서브트리로 재귀호출 return T;                                  현재 서브트리의 루트 포인터 } Data Structure

  28. 7. 이진 탐색 트리 • Binary Search Tree (이진 탐색 트리)의 삭제 • When we delete a node, we need to consider how we take care of the children of the deleted node. • This has to be done such that the property of the search tree is maintained. Data Structure

  29. 7. 이진 탐색 트리 • Binary Search Tree (이진 탐색 트리)의 삭제 • Case I] 삭제할 노드가 Leaf Node인 경우 • 자식이 없어서 간단함. • 노드 A 삭제  부모노드 B의 LChild를 널로 • 노드 K 삭제  부모노드 H의 RChild를 널로 if (T->Data.Key = = Key) {  if ((T->LChild = = NULL) && (T->RChild = = NULL)) { Nptr Temp = T; T = NULL; Delete Temp; } : : } Data Structure

  30. 7. 이진 탐색 트리 • Binary Search Tree (이진 탐색 트리)의 삭제 • Case II] 삭제할 노드가 하나의 자식노드를 거느린 경우 • 역시 간단함. • 노드 F 삭제  F의 부모노드가 F의 자식노드를 가리키면 됨 • 노드 L 삭제  G의 RChild가 H를 가리키면됨 Data Structure

  31. 7. 이진 탐색 트리 • Binary Search Tree (이진 탐색 트리)의 삭제 • Case II] 삭제할 노드가 하나의 자식노드를 거느린 경우 if (T->Data.Key = = Key) {  : else if (T->LChild = = NULL) { Nptr Temp = T; T = T->RChild; Delete Temp;     } else if (T->RChild = = NULL) { Nptr Temp = T; T = T->LChild; Delete Temp;        } : } Data Structure

  32. 7. 이진 탐색 트리 • Binary Search Tree (이진 탐색 트리)의 삭제 • Case III-1] 삭제할 노드가 두개의 자식노드를 거느린 경우 • 노드 B를 삭제 B의 부모인 F의 LChild가 동시에 A와 D를 가리키게? • D가 B로 복사. 원래의 D를 삭제. • 이진 탐색트리의 키 크기 관계는 유지 • A < B < D 관계이므로 B가 없어지면 당연히 A < D 임 • B의 자리에 D (or A) 가 와도, B보다 작았던 A의 위치는 이진 트리 정의에 합치 Data Structure

  33. 7. 이진 탐색 트리 • Binary Search Tree (이진 탐색 트리)의 삭제 • Case III-2] 두 개의 자식노드를 거느린 G를 삭제할 경우 • 이진 탐색트리를 중위순회(In-order Traversal)하면 정렬된 결과 • A, B, D, F, G, H, K, L. 크기 면에서 A < B < D < F < G < H < K < L • G가 삭제된 후에도 정렬된 순서를 그대로 유지하려면 G의 자리에는 G의 바로 오른쪽 H나, 아니면 G의 바로 왼쪽 F가 들어가야 함. • G 바로 다음에 나오는 H를 G의 중위 후속자(In-order Successor, 後續者)라 하고, G 바로 직전에 나오는 F를 G의 중위 선행자(In-order Predecessor, 先行者)라고 함. Data Structure

  34. 7. 이진 탐색 트리 • Binary Search Tree (이진 탐색 트리)의 삭제 void Delete(Nptr T, int Key) { if (T = = NULL)                       printf("No Record with Such Key"); else if (T->Data.Key > Key) Delete(T->LChild, Key);  else if (T->Data.Key < Key)            Delete(T->RChild, Key);   else if (T->Data.Key = = Key) {   if ((T->LChild = = NULL) && (T->RChild = = NULL)){ Nptr Temp = T; T = NULL; Delete Temp; } else if (T->LChild = = NULL) { Nptr Temp = T; T = T->RChild; Delete Temp; } else if (T->RChild = = NULL) { Nptr Temp = T; T = T->LChild; Delete Temp; } else SuccessorCopy(T->RChild, &(T->Data)); } } Data Structure

  35. 7. 이진 탐색 트리 • Binary Search Tree (이진 탐색 트리)의 삭제 void SuccessorCopy(Nptr T, dataType* DelNodeData) { if (T->LChild = = NULL) { (*DelNodeData).Key = T->Data.Key; Nptr Temp = T;                                 T = T->RChild; delete Temp;       } else          SuccessorCopy(T->LChild, DelNodeData); } Data Structure

  36. 7. 이진 탐색 트리 • Binary Search Tree (이진 탐색 트리)의 삭제 Flash 예제 (Click) Data Structure

  37. 7. 이진 탐색 트리 • Binary Search Tree (이진 탐색 트리)의 삭제 get max of left subtree get min of rightsubtree Data Structure

  38. 7. 이진 탐색 트리 • 키 Lee인 노드를 찾기 • Park, Kim, Lee(왼쪽 트리) 대 Cho, Kim, Lee(오른쪽 트리) • 키 Yoo인 노드 찾기 • Park, Seo, Yoo: (왼쪽 트리) 대 Cho, Kim, Lee, Park, Seo, Yoo (오른쪽 트리) Data Structure

  39. 7. 이진 탐색 트리 • 균형 • 왼쪽 트리는 완전한 균형. 오른쪽 트리는 왼쪽 서브트리의 높이가-1(빈 트리), 오른쪽 서브트리의 높이가 4로서 균형이 무너짐. • 최악의 경우 탐색은 Leaf Node까지 • 왼쪽 트리는 최악의 경우에도 높이가 2. 오른쪽 트리는 최악의 경우 높이 5를 모두 타고 내려와야 함. • 오른쪽 트리는 연결 리스트(Linked List)에 가까움. 연결이 한쪽으로 일직선으로(Linear Structure) 진행하는 트리편향 이진트리 (Skewed Binary Tree) Data Structure

  40. 7. 이진 탐색 트리 • 이진 탐색 트리에서의 탐색 효율 • 균형이 잘 잡혀있는 경우 • 높이는 lgN에 가까움. 높이만큼 키 비교를 요함. • 효율 O(lgN) • 균형이 무너진 경우 • 최악의 경우 연결 리스트에 가까움 • 효율 O(N) Data Structure

  41. 7. 이진 탐색 트리 • 자료구조별 탐색효율 비교 • O(N)과 O(lnN) 의 성능 차이는 매우 크다. • 기존 N이 1000 • N이 1000배 늘어난다고 가정 • 1000 * 1000 = 1000000 • ln(1000*1000) = ln1000 + ln1000  10 + 10 = 20 세 가지 작업에 대해 모두 lnN에 가까운 복잡도 Data Structure

More Related