자료구조. 제 5 장 트리. 5.1 서론. 5.1 서론. ▶ 트리 트리 : 하나이상의 노드 (node) 로 이루어진 유한집합 . ① 하나의 루트 노드 (root node) ② 나머지 노드들은 n( ≥ 0) 개의 분리 집합 (disjoint set) T 1 , T 2 , … , T n 으로 분할 (T i : 서브트리 ) • 노드의 차수 (degree) : 노드의 서브트리 수 • 단말 (terminal) 노드 : 차수 = 0, leaf • 비단말 노드 : 차수 0
Une image / un lien ci-dessous est fourni (tel quel) pour télécharger la présentation
Politique de téléchargement : le contenu du site vous est fourni TEL QUEL pour votre information et votre usage personnel ; il ne peut être vendu, concédé sous licence ni partagé sur d’autres sites sans l’accord de son auteur.Le contenu vous est fourni TEL QUEL, pour votre information et votre usage personnel uniquement.Téléchargez la présentation en cliquant sur ce lien.Lors du téléchargement, si vous ne parvenez pas à télécharger une présentation, l’éditeur a peut-être supprimé le fichier de son serveur.Pendant le téléchargement, si vous ne parvenez pas à obtenir une présentation, le fichier a peut-être été supprimé par l’éditeur.
5.2 이진 트리(Binary tree) • ▶ 추상 데이타 타입 • [정의] 노드의 유한 집합 • - 공백 • - 루트와 두개의 분리된 이진 트리 • (왼쪽 서브트리, 오른쪽 서브트리)
5.2 이진 트리(Binary tree) • ----------------------------------------- • template <class KeyType> • class BinaryTree{ • // objects: 공백이거나 루트 노드, 왼쪽 이진 트리, 오른쪽 • //이진 트리로 구성되는 노드들의 유한집합 • public: • BinaryTree();// 공백 이진 트리를 생성 • Boolean IsEmpty(); • // 이진 트리가 공백이면 TRUE(1) 반환; 그렇지 않으면 • // FALSE(0) 반환 • BinaryTree(BinaryTreebt1, Element<KeyType> item, • BinaryTreebt2);// 왼쪽 서브트리가 bt1, 오른쪽 서브트 • //리가 bt2, 루트 노드가 item을 갖는 이진트리를 생성 • BinaryTreeLchild(); • // IsEmpty()이면 에러 반환; 그렇지 않으면 *this의 왼쪽 • //서브트리 반환 • Element<KeyType> Data(); • // IsEmpty()이면 에러 반환; 그렇지 않으면 *this의 루트 • //노드의 데이타 반환 • BinaryTreeRchild(); • // IsEmpty()이면 에러 반환; 그렇지 않으면 *this의 오른 • //쪽 서브트리 반환 • }; • ----------------------------------------- • ADT5.1: 추상 데이타 타입 BinaryTree
5.2 이진 트리(Binary tree) • - 이진 트리와 일반 트리의 차이점 • •공백 이진 트리 존재 • •서브트리의 순서 중요 • 그림 5.9: 서로 다른 두 이진 트리 • 그림 5.10 : 편향 트리와 완전 이진 트리 • * 트리는 모두 2진 트리로 표현 가능
5.2 이진 트리(Binary tree) • ▶ 이진 트리의 특성 • - 보조정리 5.2[최대 노드수] • ⑴ 레벨 i에서의 최대 노드수 : 2i-1(i 1) • ⑵ 깊이가 k인 이진 트리가 가질수 있는 최대 노드수 • : 2k - 1(k 1) • - 보조정리 5.3 • [단말노드 수와 차수가 2인 노드 수와의 상관관계] • 공백이 아닌 모든 이진 트리 T에 대하여, • n0 : 단말 노드수 • n2 : 차수가 2인 노드 수 • n0 = n2 + 1 • ∵ n : 전체 노드수, B :전체 간선수(n1+2n2) • n1 : 차수가 1인 노드수 • n = n0 + n1+ n2 • - n = B + 1 = n1 + 2n2 +1 • ---------------------------- • n0 = n2 + 1
5.2 이진 트리(Binary tree) • - 포화 이진 트리(full binary tree) • •깊이가 K이고 • •노드수가 2K-1 인 이진 트리 • •노드 번호 1, ··· , 2k-1 까지 순차적 부여 가능 • 그림 5.11: 순차적 노드 번호를 붙인 깊이 4의 포화 이진 트리
5.2 이진 트리(Binary tree) • - 완전 이진 트리(Complete binary tree) • •이진 트리 (n 노드, 깊이 k) • •각 노드는 깊이가 k인 포화 이진 트리의 노드 번호 1부터 n까지 순차적으로 대응 • n 노드 완전 이진 트리의 높이 : log2(n+1)
5.2 이진 트리(Binary tree) • - 보조정리 5.4 • 완전이진트리(n), i: 노드번호, 트리깊이= log2(n+1) • ① PARENT(i) :i/2 if i 1 • ② LCHILD(i) : 2i if 2i n • otherwise no left child • ③ RCHILD(i) : 2i+1 if 2i+1 n • otherwise no right child
5.2 이진 트리(Binary tree) • ▶ 이진 트리의 표현 방법 • - 이진 트리의 배열 표현 • ① 완전 이진 트리 : 낭비 공간 없음 • ② 편향 이진 트리(깊이 k) : 2k-1중 k만 사용(최악의 경우)
5.2 이진 트리(Binary tree) • - 링크 표현 • 그림 5.13 : 노드 표현 • class Tree; //전방 선언 • class TreeNode { • friend class Tree; • private: • TreeNode*LeftChild; • char data; • TreeNode*RightChild; • }; • class Tree { • public: • // 트리 연산들 • ... • private: • TreeNode*root; • };
5.3 이진 트리의 순회와 트리 반복자 • - 완전한 순회는 노드의 선형 순서를 생성. • L : 왼쪽 이동 • D : 노드방문(데이타 출력) • R : 오른쪽 이동 • •순회 방법 : LDR, LRD, DLR, DRL, RDL, RLD • •왼쪽을 오른쪽보다 먼저 방문(LR) • LDR(inorder) : infix • DLR(preorder) : prefix • LRD(postorder) : postfix • note : "Data"의 위치 • •산술식의 이진트리 표현 • 그림 5.16
5.3 이진 트리의 순회와 트리 반복자 • ▶ 중위 순회(Inordertraversal) • LDR • ① 왼쪽 서브트리 순회 • ② 루트 방문 (print root) • ③ 오른쪽 서브트리 순회 • ----------------------------------------- • 1 void Tree::inorder() • 2 // 전체 트리를 순회하는 Driver는 Workhorse를 호출하며 • 3 // Driver는 Tree 클래스의 공용 멤버 함수로 선언됨. • 4 { • 5 inorder(root); • 6 } • 7 void Tree::inorder(TreeNode*CurrentNode) • 8 // Workhorse는 이진 트리의 한 노드에 대한 포인터인 • 9 //CurrentNode가 루트인 서브 트리를 순회함. • //이 Workhorse는 Tree 클래스의 전용 멤버 함수로 선언 • 10 { • 11 if (CurrentNode) { • 12 inorder(CurrentNode->LeftChild); • 13 cout<< CurrentNode->data; • 14 inorder(CurrentNode->RightChild); • 15 } • 16 } • ----------------------------------------- • 프로그램 5.1: 이진 트리의 중위 순회
5.3 이진 트리의 순회와 트리 반복자 • ▶ 전위 순회(Preorder traversal) • DLR • ① 루트 방문 • ② 왼쪽 서브트리 순회 • ③ 오른쪽 서브트리 순회 • ----------------------------------------- • 1 void Tree::preorder() • 2 // 전체 트리를 순회하는 Driver는 Workhorse를 호출하며 • 3 // Driver는 Tree 클래스의 공용 멤버 함수로 선언됨. • 4 { • 5 preorder(root); • 6 } • 7 void Tree::preorder(TreeNode*CurrentNode) { • 8 // Workhorse는 CurrentNode(이진 트리의 한 노드에 대한 • 9 // 포인터)를 루트로하는 서브 트리를 순회한다. 이 • 10 // Workhorse는 Tree 클래스의 전용 멤버 함수로 선언됨. • 11 if (CurrentNode) { • 12 cout<< CurrentNode->data; • 13 preorder(CurrentNode->LeftChild); • 14 preorder(CurrentNode->RightChild); • 15 } • 16 } • ----------------------------------------- • 프로그램 5.2: 이진 트리의 전위 순회 • Output : +**/ABCDE(수식의 전위 표기)
5.3 이진 트리의 순회와 트리 반복자 • ▶ 후위 순회(Postorder traversal) • LRD • ① 왼쪽 서브트리 순회 • ② 오른쪽 서브트리 순회 • ③ 루트 방문 • ----------------------------------------- • 1 void Tree::postorder() • 2 // 전체 트리를 순회하는 Driver는 Workhorse를 호출하며 • 3 // Driver는 Tree 클래스의 공용 멤버 함수로 선언됨. • 4 { • 5 postorder(root); • 6 } • 7 void Tree::postorder(TreeNode*CurrentNode) • 8 // Workhorse는 CurrentNode(이진 트리의 한 노드에 대한 • 9 // 포인터)를루트로 하는 서브 트리를 순회한다. 이 • 10 // Workhorse는 Tree 클래스의 전용 멤버 함수로 선언됨. • 11 if (CurrentNode) { • 12 postorder(CurrentNode->LeftChild); • 13 postorder(CurrentNode->RightChild); • 14 cout<< CurrentNode->data; • 15 } • 16 } • ----------------------------------------- • 프로그램 5.3: 이진 트리의 후위 순회 • Output : AB/C*D*E+ (수식의 후위 표기)
5.3 이진 트리의 순회와 트리 반복자 • ▶ 반복적 중위 순회 • •스택을 사용 • •링크로 표현된 이진 트리 • •알고리즘의 작성 방법 • ① recursive method • ~ an internal stack • ② non-recursive method • ~ an extenalstack • ③ non-recursive stacklessmethod • ~ parent field • ④ nonrecursivestacklessmethod • ~ thread, no parent field • ⑤ nonrecursivestacklessmethod • ~ unthreaded, no parent field
5.3 이진 트리의 순회와 트리 반복자 • ----------------------------------------- • class InorderIterator { • public: • char *Next(); • InorderIterator(Tree tree) : t(tree) { • CurrentNode= t.root; • }; • private: • Tree t; • Stack <TreeNode*> s; • TreeNode*CurrentNode; • }; • ----------------------------------------- • 프로그램 5.5: 중위 반복자 클래스의 정의
5.3 이진 트리의 순회와 트리 반복자 • ----------------------------------------- • char *InorderIterator::Next() • { • while(CurrentNode) { • s.add(CurrentNode); • CurrentNode= CurrentNode->LeftChild; • } • if (!s.IsEmpty()) { • CurrentNode= *s.Delete(CurrentNode); • char &temp = CurrentNode->data; • CurrentNode= CurrentNode->RightChild; • //CurrentNode를 수정 • return &temp; • } • else return 0; // 트리가 순회되었고 더 이상 원소 없음 • } • ----------------------------------------- • 프로그램 5.6: 다음 중위 원소를 가져오는 코드
5.3 이진 트리의 순회와 트리 반복자 • ▶ 레벨 순서 순회 • •큐를 사용. • 그림 5.16을 레벨 순회한 결과 : +*E*D/CAB • ----------------------------------------- • void Tree::LevelOrder() • // 이진 트리의 레벨 순서 순회 • { • QUEUE<TreeNode*> q; • TreeNode*CurrentNode= root; • while(CurrentNode) { • cout<<CurrentNode->data<<endl; • if (CurrentNode->LeftChild) • q.add(CurrentNode->LeftChild); • if (CurrentNode->RightChild) • q.add(CurrentNode->RightChild); • CurrentNode= *q.Delete(CurrentNode); • } • } • ----------------------------------------- • 프로그램 5.7: 이진 트리의 레벨 순서 순회
5.3 이진 트리의 순회와 트리 반복자 • ▶ 스택없는 순회 • - 각 노드에 parent 필드 추가. • - 각 노드에 두 비트가 필요. • 이진 트리를 스레드(thread)이진 트리로 표현.
5.4 이진 트리의 추가 연산 • ▶ 이진 트리의 복사 • ----------------------------------------- • // 복사 생성자(copy constructor) • Tree::Tree(constTree &s) // Driver • { • root = copy(s.root); • } • TreeNode*Tree::copy(TreeNode*orignode) // Workhorse • // 이 함수는 루트가 orignode인 트리를 복사하여 복사된 트 • // 리의 포인터를 반환한다. • { • if (orignode) { • TreeNode*temp = new TreeNode; • temp->data = orignode->data; • temp->LeftChild= copy(orignode->LeftChild); • temp->RightChild= copy(orignode->RightChild); • return temp; • } • else return 0; • } • ----------------------------------------- • 프로그램 5.9: 이진 트리의 복사
5.4 이진 트리의 추가 연산 • ▶ 이진 트리의 동일성 • - 동일한 구조 • - 동일한 정보 • ----------------------------------------- • // Driver - Tree 클래스의 friend로 가정. • int operator==(constTree& s, Tree& t) • { • return equal(s.root, t.root); • } • // Workhorse - TreeNode클래스의 friend로 가정. • int equal(TreeNode*a, TreeNode*b) • // 이 함수는 a와 b의 서브트리들이 동일하지 않으면 0을, 동일하면 1을 반환한다. • { • if ((!a) && (!b)) return 1; // a, b 둘다 0 • if (a && b && (a->data == b->data) // data가 같다 • && equal(a->LeftChild, b->LeftChild) // 왼쪽 서브트리 //가 같다 • && equal(a->RightChild, b->RightChild)) //오른쪽 서브 • //트리가 같다 • return 1; • return 0; • } • ----------------------------------------- • 프로그램 5.10: 이진 트리 동일성
5.4 이진 트리의 추가 연산 • ▶ 만족성 문제 • 명제 해석(propositional calculus) • - 불리언 변수 x1, x2, ...., xn 과 연산자 ∧,∨,¬로 이루어진식 • - { T, F } 로 사상 • ⑴ 변수 자체도 하나의 식 • ⑵ x,y가 식 일때, ¬x, x∧y, x∨y 도 식 • ⑶ 연산순서는 ¬,∧,∨.
5.4 이진 트리의 추가 연산 • (x1∧¬x2)∨(¬x1∧x3)∨¬x3 • 그림 5.18 : 이진 트리로 표현된 명제식 • - 중위순회 : x1∧¬x2∨¬x1∧x3∨¬x3 • x1 x2 x3 formula • T T T ? • T T F ? evaluation : • T F T ? postorder traversal • T F F ? • . • :
5.4 이진 트리의 추가 연산 • - 후위 순회 계산 • data : boolean variable or boolean operator • value : T, F
5.4 이진 트리의 추가 연산 • enumBoolean {FALSE, TRUE}; • enumTypesOfData {LogicalNot, LogicalAnd, LogicalOr, • LogicalTrue, LogicalFalse}; • class SatTree; // 전방 선언 • class SatNode { • friend class SatTree; • private: • SatNode*LeftChild; • TypesOfDatadata; • Boolean value; • SatNode*RightChild; • }; • class SatTree { • public • void PostOrderEval(): • void rootvalue() { cout<< root->value;} ; • private: • SatNode*root; • void PostOrderEval(SatNode*); • };
5.4 이진 트리의 추가 연산 • ----------------------------------------- • for n변수에 대한 2n개의 가능한 참값 조합 • { • 다음 조합을 생성; • 그들의 값을 변수에 대입; • 명제식을 나타내는 트리를 후위 순회로 계산; • if (formula.rootvalue()) { cout<< combination; return; } • } • cout<< "no satisfiablecombination"; • ----------------------------------------- • 프로그램 5.11: 만족성 알고리즘의 첫번째 버전
5.4 이진 트리의 추가 연산 • ----------------------------------------- • void SatTree::PostOrderEval() // Driver • { PostOrderEval(root); } • void SatTree::PostOrderEval(SatNode*s) // Workhorse • { • if (s) { • PostOrderEval(s->LeftChild); • PostOrderEval(s->RightChild); • switch(s->data) { • case LogicalNot: s->value = !s->RightChild->value; break; • case LogicalAnd: s->value = • s->RightChild->value && s->LeftChild->value; • break; • case LogicalOr: • s->value = s->RightChild->value || • s->LeftChild->value; • break; • case LogicalTrue: s->value = TRUE; break; • case LogicalFalse: s->value = FALSE; • } • } • } • ----------------------------------------- • 프로그램 5.12: 명제식의 계산
5.5 스레드 이진 트리 • - 스레드 이진 트리의 표현 • LeftThread== F : LeftChild←pointer • == T : LeftChild←thread • RightThread== F : RightChild←pointer • == T : RightChild←thread • dangling 포인터 문제 → 헤드 노드 • 공백 이진 트리 : 헤드 노드
- 스레드 이진 트리를 위한 클래스 정의 • ----------------------------------------- • class ThreadedNode { • friend class ThreadedTree; • friend class ThreadedInorderIterator; • private: • Boolean LeftThread; • ThreadedNode*LeftChild; • char data; • ThreadedNode*RightChild; • Boolean RightThread; • }; • class ThreadedTree { • friend class ThreadedInorderIterator; • public: • : // 트리 조작 연산들 • private: • ThreadedNode*root; • }; • class ThreadedInorderIterator { • public: • char *Next(); • ThreadedInorderIterator(ThreadedTreetree):t(tree) • CurrentNode= t.root; ; • private: • ThreadedTreet; • ThreadedNode*CurrentNode; • }; • -----------------------------------------
5.5 스레드 이진 트리 • - 스레드 이진 트리의 메모리 표현 • 주의 : 헤드 노드의 왼쪽 서브트리
5.5 스레드 이진 트리 • ▶ 스레드 이진 트리의 중위 순회 • •스택을 이용하지 않고 순회 • •중위 순회의 후속자 • RightThread == T : RightChild • == F : 오른쪽 자식의 왼쪽 자식 링크를 따라 • LeftThread == TRUE인 노드 • - 스레드 이진 트리에서 중위 후속자를 찾는 함수 • ----------------------------------------- • char *ThreadedInorderIterator::Next() { • // 스레드 이진 트리에서 CurrentNode의 중위 후속자를 찾는다 • ThreadedNode *temp = CurrentNode->RightChild; • if (!CurrentNode->RightThread) • while (!temp->LeftThread) temp = temp->LeftChild; • CurrentNode = temp; • if (CurrentNode==t.root) return 0; • else return &CurrentNode->data; • } • ----------------------------------------- • - 스레드 이진 트리의 중위 순회 • ----------------------------------------- • void ThreadedInorderIterator::Inorder() { • for (char *ch=Next(); ch; ch = Next()) cout<< *ch << endl; • } • -----------------------------------------
5.5 스레드 이진 트리 • ▶ 스레드 이진 트리에서의 노드 삽입 • - s의 오른쪽 자식으로 r을 삽입