21
이진 트리 순회와 트리 반복자 트리 순회(tree traversal) 트리에 있는 모든 노드를 번씩만 방문 순회 방법 : LVR, LRV, VLR, VRL, RVL, RLV L : 왼쪽 이동, V : 노드방문, R : 오른쪽 이동 왼쪽을 오른쪽보다 먼저 방문(LR) LVR : 중위(inorder) 순회 VLR : 전위(preorder) 순회 LRV : 후위(postorder) 순회 산술식의 이진트리 표현 + * / B C A D E * 1

이진 트리 순회와 트리 반복자 - lms.kumoh.ac.krlms.kumoh.ac.kr/.../contents/20141CS000801/13주차.ch05.트리.pdf · 이진 트리 순회와 트리 반복자 ... 만족성

Embed Size (px)

Citation preview

Page 1: 이진 트리 순회와 트리 반복자 - lms.kumoh.ac.krlms.kumoh.ac.kr/.../contents/20141CS000801/13주차.ch05.트리.pdf · 이진 트리 순회와 트리 반복자 ... 만족성

이진 트리 순회와 트리 반복자

트리 순회(tree traversal) 트리에 있는 모든 노드를 한 번씩만 방문 순회 방법 : LVR, LRV, VLR, VRL, RVL, RLV

L : 왼쪽 이동, V : 노드방문, R : 오른쪽 이동

왼쪽을 오른쪽보다 먼저 방문(LR) LVR : 중위(inorder) 순회 VLR : 전위(preorder) 순회 LRV : 후위(postorder) 순회

산술식의 이진트리 표현 +

*

/

B

C

A

D

E

*

1

Page 2: 이진 트리 순회와 트리 반복자 - lms.kumoh.ac.krlms.kumoh.ac.kr/.../contents/20141CS000801/13주차.ch05.트리.pdf · 이진 트리 순회와 트리 반복자 ... 만족성

이진 트리 순회와 트리 반복자

=============================================== 1 template <class T> 2 void Tree<T>::Inorder() 3 {// Driver calls workhorse for traversal of entire tree. The driver is 4 // declared as a public member function of Tree. 5 Inorder(root); 6 } 7 template <class T> 8 void Tree<T>::Inorder(TreeNode<T> *currentNode) 9 {// Workhorse traverses the subtree rooted at currentNode. 10 // The workhorse is declared as a private member function of Tree. 11 if (currentNode) { 12 Inorder(currentNode->leftChild); 13 Visit(currentNode); 14 Inorder(currentNode->rightChild); 15 } 16 } ===============================================

2

Page 3: 이진 트리 순회와 트리 반복자 - lms.kumoh.ac.krlms.kumoh.ac.kr/.../contents/20141CS000801/13주차.ch05.트리.pdf · 이진 트리 순회와 트리 반복자 ... 만족성

Inorder traversal (중위 순회)

호출

Driver 1 2 3 4 5 4 6 3 7 8 7 9 2

+ * * / A 0 A 0 / B 0 B 0 *

cout<<‘A’

cout<<‘/’

cout<<‘B’

cout<<‘*’

currentNode의 값 조치 호출

10 11 10 12 1

13 14 13 15

Driver 16 17 16 18

C 0 C 0 * D 0 D 0 + E 0 E 0

cout<<‘C’

cout<<‘*’

cout<<‘D’

cout<<‘+’

cout<<‘E’

currentNode의 값 조치

출력 : A/B*C*D+E

+

*

/

B

C

A

D

E

*

3

Page 4: 이진 트리 순회와 트리 반복자 - lms.kumoh.ac.krlms.kumoh.ac.kr/.../contents/20141CS000801/13주차.ch05.트리.pdf · 이진 트리 순회와 트리 반복자 ... 만족성

Preorder Traversal (전위 순회)

출력 : +**/ABCDE

+

*

/

B

C

A

D

E

*

4

Program 5.2:Preorder traversal of a binary tree =============================================== 1 template <class T> 2 void Tree<T>::Preorder() 3 {// Driver. 4 Preorder(root); 5 } 6 template <class T> 7 void Tree<T>::Preorder(TreeNode<T> *currentNode) 8 {// Workhorse. 9 if (currentNode) { 10 Visit(currentNode); 11 Preorder(currentNode->leftChild); 12 Preorder(currentNode->rightChild); 13 } 14 } ===============================================

Page 5: 이진 트리 순회와 트리 반복자 - lms.kumoh.ac.krlms.kumoh.ac.kr/.../contents/20141CS000801/13주차.ch05.트리.pdf · 이진 트리 순회와 트리 반복자 ... 만족성

Postorder Traversal (전위 순회)

출력 : AB/C*D*E+

+

*

/

B

C

A

D

E

*

5

=============================================== 1 template <class T> 2 void Tree<T>::Postorder() 3 {// Driver. 4 Postorder(root); 5 } 6 template <class T> 7 void Tree<T>::Postorder(TreeNode<T> *currentNode) 8 {// Workhorse. 9 if (currentNode) { 10 Postorder(currentNode->leftChild); 11 Postorder(currentNode->rightChild); 12 Visit(currentNode); 13 } 14 } ===============================================

Page 6: 이진 트리 순회와 트리 반복자 - lms.kumoh.ac.krlms.kumoh.ac.kr/.../contents/20141CS000801/13주차.ch05.트리.pdf · 이진 트리 순회와 트리 반복자 ... 만족성

비순환 중위 순회

=============================================== 1 template <class T> 2 void Tree<T>::NonrecInorder() 3 {// Nonrecursive inorder traversal using a stack. 4 Stack<TreeNode<T>*> s; // declare and initialize stack 5 TreeNode<T> *currentNode = root; 6 while(1) { 7 while (currentNode) { // move down leftChild fields 8 s.Push(currentNode); // add to stack 9 currentNode = currentNode->leftChild; 10 } 11 if (s.IsEmpty()) return; 12 currentNode = s.Top(); 13 s.Pop(); // delete from stack 14 Visit(currentNode); 15 currentNode = currentNode->rightChild; 16 } 17 } ===============================================

6

Page 7: 이진 트리 순회와 트리 반복자 - lms.kumoh.ac.krlms.kumoh.ac.kr/.../contents/20141CS000801/13주차.ch05.트리.pdf · 이진 트리 순회와 트리 반복자 ... 만족성

Level Order Traversal(레벨 순서 순회)

큐 사용

루트 방문->왼쪽 자식 방문->오른쪽 자식 방문

+ * E * D / C A B

template <class T> void Tree<T>::LevelOrder() {//이진 트리의 레벨 순서 순회 Queue<TreeNode<T>*> q; TreeNode<T> * currentNode = root; while(currentNode){ Visit(currentNode); if(currentNode->leftChild) q.Push(currentNode->leftChild); if(currentNode->rightChild) q.Push(currentNode->rightChild); if(q.IsEmpty()) return; currentNode = q.Front(); q.Pop(); } }

+

*

/

B

C

A

D

E

*

7

Page 8: 이진 트리 순회와 트리 반복자 - lms.kumoh.ac.krlms.kumoh.ac.kr/.../contents/20141CS000801/13주차.ch05.트리.pdf · 이진 트리 순회와 트리 반복자 ... 만족성

스택 없는 순회

각 노드에 parent (부모)필드 추가 스택을 사용하지 않아도 루트 노드로 올라갈 수 있음

스레드(thread)이진 트리로 표현 각 노드마다 두 비트 필요 leftChild필드와 rightChild 필드를 루트로 돌아갈 수 있는 경로를 유지하도록 사용

경로 상의 주소 스택은 리프 노드에 저장

A

root

B

E 0 D

0 H 0 0 I 0

C

0 G 0 0 F 0

A

B

D

H I

E

C

F G

root

8

Page 9: 이진 트리 순회와 트리 반복자 - lms.kumoh.ac.krlms.kumoh.ac.kr/.../contents/20141CS000801/13주차.ch05.트리.pdf · 이진 트리 순회와 트리 반복자 ... 만족성

이진트리의 추가 연산

복사 : 프로그램 5.9 동일성 검사 : 프로그램 5.10 재귀 함수로 구현

만족성 문제 변수 x1, x2 , … , xn 과 연산자 ∧, ∨, ¬으로 이루어진 식 변수 = {참, 거짓} 규칙

(1) 변수도 하나의 식 (2) x, y가 식일때, ¬x, x∧y, x∨y 도 식 (3) 연산순서는 ¬, ∧, ∨ 순, 괄호 사용

명제 해석식(formula of propositional calculus) 위 규칙을 이용해서 구성한 식

)( 321 xxx ¬∧∨

9

Page 10: 이진 트리 순회와 트리 반복자 - lms.kumoh.ac.krlms.kumoh.ac.kr/.../contents/20141CS000801/13주차.ch05.트리.pdf · 이진 트리 순회와 트리 반복자 ... 만족성

Program 5.9:Copying a binary tree =============================================== template <class T> Tree<T>::Tree(const Tree<T>& s) // driver {// Copy constructor root = Copy(s.root); } template <class T> TreeNode<T>* Tree<T>::Copy(TreeNode<T> *origNode) // Workhorse {// Return a pointer to an exact copy of the binary tree rooted at origNode. if (!origNode) return 0; else return new TreeNode<T>(origNode->data, Copy(origNode->leftChild), Copy(origNode->rightChild)); } template <class T> Tree<T>::Tree(T data, TreeNode<T> *lChild, TreeNode<T> * rChild) : data(d), leftChild(lChild), rightChild(rChild) { } ===============================================

Page 11: 이진 트리 순회와 트리 반복자 - lms.kumoh.ac.krlms.kumoh.ac.kr/.../contents/20141CS000801/13주차.ch05.트리.pdf · 이진 트리 순회와 트리 반복자 ... 만족성

Program 5.10:Binary tree equivalence =============================================== template <class T> bool Tree<T>::operator==(const Tree& t) const { return Equal(root, t.root); } template <class T> bool Tree<T>::Equal(TreeNode<T> *a, TreeNode<T> *b) {// Workhorse. if ((!a) && (!b)) return true; // both a and b are 0 else return (a && b // both a and b are non-zero && (a->data == b->data) // data is the same && Equal(a->leftChild, b->leftChild) // left subtrees equal && Equal(a->rightChild, b->rightChild)); // right subtrees equal } ===============================================

Page 12: 이진 트리 순회와 트리 반복자 - lms.kumoh.ac.krlms.kumoh.ac.kr/.../contents/20141CS000801/13주차.ch05.트리.pdf · 이진 트리 순회와 트리 반복자 ... 만족성

만족성 문제 (1)

명제식의 만족성(satisfiability) 문제 식의 값이 true가 되도록, 변수에 값을 지정할 수 있는 방법이 있는가?

33121 )()( xxxxx ¬∨∧¬∨¬∧

¬

x3

x1 ¬

¬ x3

x2 x1

12

Page 13: 이진 트리 순회와 트리 반복자 - lms.kumoh.ac.krlms.kumoh.ac.kr/.../contents/20141CS000801/13주차.ch05.트리.pdf · 이진 트리 순회와 트리 반복자 ... 만족성

만족성 문제 (2)

가능한 모든 true와 false의 조합을 대입 : O(g 2n) g : 식을 계산하는데 필요한 시간 전체 식이 하나의 값이 될 때까지 서브 트리를 계산하면서 트리 후위 순회

x1 x2 x3 formular T T T ? T T F ? T F T ? T F F ? F T T ? F T F ? F F T ? F F F ?

13

¬

x3

x1 ¬

¬ x3

x2 x1

∨¬∨∧¬∧¬ 33121 xxxxx

Page 14: 이진 트리 순회와 트리 반복자 - lms.kumoh.ac.krlms.kumoh.ac.kr/.../contents/20141CS000801/13주차.ch05.트리.pdf · 이진 트리 순회와 트리 반복자 ... 만족성

만족성 문제 (3)

후위 순회 계산 Tree 템플릿 클래스를 T=pair<Operator, bool>로 인스턴스화 enum Operator { Not, And, Or, True, False};

for n개 변수에 대한 2n개의 가능한 참값 조합 { 다음 조합을 생성; 그들의 값을 변수에 대입; 명제식을 나타내는 트리를 후위 순회로 계산; if(formula.Data().second()){cout << current combination; return;} } cout <<“no satisfiable combination”;

// visit the node pointed at by p switch (p->data.first) { case Not: p->data.second = !p->rightChild->data.second; break; case And: p->data.second = p->leftChild->data.second && p->rightChild->data.second; break; case Or: p->data.second = p->leftChild->data.second || p->rightChild->data.second; break; case True: p->data.second = true; break; case False: p->data.second = false; } 14

Page 15: 이진 트리 순회와 트리 반복자 - lms.kumoh.ac.krlms.kumoh.ac.kr/.../contents/20141CS000801/13주차.ch05.트리.pdf · 이진 트리 순회와 트리 반복자 ... 만족성

Thread (1)

n 노드 이진 트리의 연결 표현 총 링크의 수 : 2n null 링크의 수 : n+1 > null이 아닌 링크 수 n-1

A

root

B

0 E 0 D

0 H 0 0 I 0

C

0 G 0 0 F 0

15

Page 16: 이진 트리 순회와 트리 반복자 - lms.kumoh.ac.krlms.kumoh.ac.kr/.../contents/20141CS000801/13주차.ch05.트리.pdf · 이진 트리 순회와 트리 반복자 ... 만족성

Thread (2)

스레드(Thread) 0 링크 필드를 다른 노드를 가리키는 포인터로 대치 if p->rightChild == 0,

p->rightChild = p의 중위 후속자에 대한 포인터 if p->leftChild = 0,

p->leftChild = p의 중위 선행자에 대한 포인터

A

B

D

H I

E

C

F G

root

16

순회 : H D I B E A F C G

Page 17: 이진 트리 순회와 트리 반복자 - lms.kumoh.ac.krlms.kumoh.ac.kr/.../contents/20141CS000801/13주차.ch05.트리.pdf · 이진 트리 순회와 트리 반복자 ... 만족성

Thread (3)

노드 구조: leftThread와 rightChild의 tag 필드를 사용 leftThread == false : leftChild ← 포인터

== true : leftChild ← 스레드 rightThread == false : rightChild ← 포인터

== true : rightChild ← 스레드

헤드 노드 연결되지 않은 스레드 제거

leftThread leftChild data rightChild rightThread

TRUE FALSE

17

Page 18: 이진 트리 순회와 트리 반복자 - lms.kumoh.ac.krlms.kumoh.ac.kr/.../contents/20141CS000801/13주차.ch05.트리.pdf · 이진 트리 순회와 트리 반복자 ... 만족성

스레드 이진 트리의 메모리 표현

f - f

f A f

f C f f B f

f D f t E t t F t t G t

t I t t H t

f = false; t = true

root

18

Page 19: 이진 트리 순회와 트리 반복자 - lms.kumoh.ac.krlms.kumoh.ac.kr/.../contents/20141CS000801/13주차.ch05.트리.pdf · 이진 트리 순회와 트리 반복자 ... 만족성

스레드 이진 트리의 중위 순회

스택을 이용하지 않고 중위 순회 가능

중위 순회의 후속자 x->rightThread == true : x->rightChild

== false : 오른쪽 자식의 왼쪽 자식 링크를 따라 가서 LeftThread==true인 노드

스레드 이진 트리에서 중위 후속자를 찾는 함수 T* ThreadedInorderIterator::Next() {//스레드 이진 트리에서 currentNode의 중위 후속자를 반환 ThreadedNode<T> *temp = currentNode->rightChild; if(!currentNode->rightThread) while(!temp->leftThread) temp = temp->leftChild; currentNode = temp; if(currentNode == root) return 0; else return &currentNode->data; }

19

Page 20: 이진 트리 순회와 트리 반복자 - lms.kumoh.ac.krlms.kumoh.ac.kr/.../contents/20141CS000801/13주차.ch05.트리.pdf · 이진 트리 순회와 트리 반복자 ... 만족성

스레드 이진 트리에서의 노드 삽입

s의 오른쪽 자식으로 r을 삽입

20

Page 21: 이진 트리 순회와 트리 반복자 - lms.kumoh.ac.krlms.kumoh.ac.kr/.../contents/20141CS000801/13주차.ch05.트리.pdf · 이진 트리 순회와 트리 반복자 ... 만족성

21

Program 5.14:Inserting r as the right child of s =============================================== template <class T> void ThreadedTree<T>::InsertRight(ThreadedNode<T> *s, ThreadedNode<T> *r) {// Insert r as the right child of s. r->rightChild = s->rightChild; r->rightThread = s->rightThread; r->leftChild = s; r->leftThread = true; // leftChild is a thread s->rightChild = r; s->rightThread = false; if (! r->rightThread) { ThreadedNode<T> *temp = InorderSucc(r); // returns the inorder successor of r temp->leftChild = r; } } ===============================================