|
// |
|
// Created by Cheolbak on 2016. 4. 30.. |
|
// |
|
|
|
#ifndef TREE_TREE_H |
|
#define TREE_TREE_H |
|
|
|
// Tree 클래스 구현 |
|
// 구현된 트리는 이진트리 (Binary Tree) |
|
// 템플릿 사용 후 .cpp 컴파일시 링킹이 안된다. |
|
// 따라서 .h에 구현까지 한다. |
|
|
|
#include "Stack.h" |
|
|
|
// 템플릿 선언. Tree 클래스 사용시 Tree<type>으로 써야함 |
|
// Example : Tree<int> rootNode; |
|
template <typename Data> |
|
class Tree { |
|
private: |
|
// 저장될 Data |
|
Data data; |
|
// 왼쪽, 오른쪽 Node Pointer |
|
Tree<Data> * left; |
|
Tree<Data> * right; |
|
public: |
|
Tree() : Tree(0) { } |
|
|
|
Tree(Data data) : Tree(data, nullptr, nullptr) { } |
|
|
|
Tree(Data data, Tree<Data> * left, Tree<Data> * right) { |
|
// nullptr은 C++11에서의 NULL |
|
// NULL은 기본적으로 0이므로 int로 취급됨 |
|
// nullptr은 말 그대로 0도 아닌 null이다. |
|
this->left = left; |
|
this->right = right; |
|
this->data = data; |
|
} |
|
|
|
// 데이터 삽입 및 가져오기 |
|
Data getData() { |
|
return data; |
|
} |
|
|
|
void setData(Data data) { |
|
this->data = data; |
|
} |
|
|
|
// 이진 트리의 왼쪽, 오른쪽 Node 가져오기 |
|
Tree<Data> * getLeft() { |
|
return left; |
|
} |
|
|
|
Tree<Data> * getRight() { |
|
return right; |
|
} |
|
|
|
// 이진 트리의 왼쪽, 오른쪽 Node 할당하기 |
|
void edgeLeft(Tree<Data> *child) { |
|
// 만약에 left에 할당 되어있으면 지운 후 재할당 |
|
if (left != nullptr) |
|
deleteTree(left); |
|
left = child; |
|
} |
|
|
|
void edgeRight(Tree<Data> *child) { |
|
// 만약에 right에 할당 되어있으면 지운 후 재할당 |
|
if (right != nullptr) |
|
deleteTree(right); |
|
right = child; |
|
} |
|
|
|
// Function Pointer Type Alias |
|
// 트리 순회에 사용될 함수 작성시엔 |
|
// void function(Type name) 으로 작성해야 함 |
|
using Func = void(*)(Data); |
|
|
|
// 트리 순회 함수 (Static) |
|
// 재귀 함수로 구현됨 |
|
// 중위(inorder) 순회 : 왼쪽 -> 부모 -> 오른쪽 |
|
static void inorderTraverse(Tree<Data> * node, Func process) { |
|
if (node == nullptr) |
|
return; |
|
inorderTraverse(node->left, process); |
|
process(node->data); |
|
inorderTraverse(node->right, process); |
|
} |
|
|
|
// 재귀 함수를 사용하지 않은 중위 순회 |
|
static void inorderNonRecursive(Tree<Data> * node, Func process) { |
|
Stack<Tree<Data>*> stack; |
|
while (true) { |
|
while (node != nullptr) { |
|
stack.push(node); |
|
node = node->getLeft(); |
|
} |
|
if (stack.isEmpty()) |
|
break; |
|
node = stack.pop(); |
|
process(node->getData()); |
|
node = node->getRight(); |
|
} |
|
} |
|
|
|
// 전위(preorder) 순회 : 부모 -> 왼쪽 -> 오른쪽 |
|
static void preorderTraverse(Tree<Data> * node, Func process) { |
|
if (node == nullptr) |
|
return; |
|
process(node->data); |
|
preorderTraverse(node->left, process); |
|
preorderTraverse(node->right, process); |
|
} |
|
|
|
// 재귀 함수를 사용하지 않은 전위 순회 |
|
static void preorderNonRecursive(Tree<Data> * node, Func process) { |
|
Stack<Tree<Data>*> stack; |
|
while (true) { |
|
while (node != nullptr) { |
|
process(node->getData()); |
|
stack.push(node); |
|
node = node->getLeft(); |
|
} |
|
if (stack.isEmpty()) |
|
break; |
|
node = stack.pop(); |
|
node = node->getRight(); |
|
} |
|
} |
|
|
|
// 후위(postorder) 순회 : 왼쪽 -> 오른쪽 -> 부모 |
|
static void postorderTraverse(Tree<Data> * node, Func process) { |
|
if (node == nullptr) |
|
return; |
|
postorderTraverse(node->left, process); |
|
postorderTraverse(node->right, process); |
|
process(node->data); |
|
} |
|
|
|
// 재귀 함수를 사용하지 않은 후위 순회 |
|
static void postorderNonRecursive(Tree<Data> * node, Func process) { |
|
Stack<Tree<Data>*> stack; |
|
while (true) { |
|
if (node != nullptr) { |
|
stack.push(node); |
|
node = node->getLeft(); |
|
} |
|
else { |
|
if (stack.isEmpty()) |
|
return; |
|
else { |
|
if (stack.peek()->getRight() == nullptr) { |
|
node = stack.pop(); |
|
process(node->getData()); |
|
while (!stack.isEmpty() && (node == stack.peek()->getRight())) { |
|
node = stack.pop(); |
|
process(node->getData()); |
|
} |
|
} |
|
} |
|
if (!stack.isEmpty()) |
|
node = stack.peek()->getRight(); |
|
else |
|
node = nullptr; |
|
} |
|
} |
|
} |
|
|
|
static bool getDepth(Tree<Data> *root, Tree<Data> *node, int *returnCount) { |
|
if (root == nullptr) |
|
return false; |
|
if (root->getLeft() == node || root->getRight() == node |
|
|| getDepth(root->getLeft(), node, returnCount) || getDepth(root->getRight(), node, returnCount)) { |
|
(*returnCount)++; |
|
return true; |
|
} |
|
return false; |
|
} |
|
|
|
static void visualShowTree(Tree<Data> * root, Tree<Data> * node) { |
|
if (node == nullptr) |
|
return; |
|
visualShowTree(root, node->getRight()); |
|
int * nodeDepth = new int; |
|
*nodeDepth = 0; |
|
getDepth(root, node, nodeDepth); |
|
for (int tap = 0; tap < (*nodeDepth); tap++) |
|
std::cout << '\t'; |
|
std::cout << node->getData() << std::endl; |
|
visualShowTree(root, node->getLeft()); |
|
} |
|
|
|
// 트리 삭제 : 후위 순회 |
|
static void deleteTree(Tree<Data> * node) { |
|
if (node == nullptr) |
|
return; |
|
deleteTree(node->left); |
|
deleteTree(node->right); |
|
delete node; |
|
} |
|
}; |
|
|
|
#endif //TREE_TREE_H |
|
|