반응형
스레이드 이진 트리
# 스레이드 이진 트리라는 말보다는 스레드 이진 트리라는 표현이 더 많이 쓰이는 것 같지만, 왠지 운영체제의 스레드와 혼동이 되므로 스레이드라 썼다.
# 스레이드 이진 트리는 이진트리의 순회를 재귀함수로 구현하면 시스템 스택을 사용하므로 비효율적이기 때문에 이를 영링크를 활용하여 비재귀적으로 바꾼 트리이다.
# ... 라는데 아래의 구현이 더 효율적일지는 잘 모르겠고, 일단 순회에 있어서 재귀호출을 사용하지 않게 하는데만 집중했다.
# 아무리 생각해도 구현의 난이도가 쓸데없이 높아서 사용이 많이 될지는 모르겠다.
# 저번 포스트의 전위, 중위, 후위 순회 부분만 비재귀로 바꿨다.
구현 코드
#pragma once
template <typename T>
struct node
{
T data;
node* prev;
node* next;
node* left;
node* right;
};
//트리 관련 전역 함수
template <typename T>
void ChangeData(node<T>* node, T data)
{
node->data = data;
}
template <typename T>
T& CheckData(node<T>* node)
{
return node->data;
}
template <typename T>
node<T>* MakeNode(T data)
{
node<T>* nn = new node<T>;
nn->data = data;
nn->left = nullptr;
nn->right = nullptr;
nn->prev = nullptr;
nn->next = nullptr;
return nn;
}
//작업을 함수포인터로 전달받는 순회 함수
template <typename T>
void preorder(node<T>* _node, void(*action)(T))
{
node<T>* nptr = _node;
while (nptr != nullptr) {
if (nptr->left != nullptr) {
if (nptr->right != nullptr) {
nptr->left->next = nptr->right;
}
else {
nptr->left->next = nptr->next;
}
}
if(nptr->right != nullptr) {
nptr->right->next = nptr->next;
}
action(nptr->data);
if (nptr->left != nullptr) {
nptr = nptr->left;
}
else if (nptr->right != nullptr) {
nptr = nptr->right;
}
else {
nptr = nptr->next;
}
}
}
template <typename T>
void inorder(node<T>* _node, void(*action)(T))
{
node<T>* nptr = _node;
while (nptr->left != nullptr) {
if (nptr->left != nullptr) {
nptr->left->next = nptr;
}
if (nptr->right != nullptr) {
nptr->right->next = nptr->next;
}
nptr = nptr->left;
}
while (nptr != nullptr) {
if (nptr->left != nullptr) {
nptr->left->next = nptr;
}
if (nptr->right != nullptr) {
nptr->right->next = nptr->next;
}
action(nptr->data);
if (nptr->right != nullptr) {
nptr = nptr->right;
while (nptr->left != nullptr) {
if (nptr->left != nullptr) {
nptr->left->next = nptr;
}
if (nptr->right != nullptr) {
nptr->right->next = nptr->next;
}
nptr = nptr->left;
}
}
else {
nptr = nptr->next;
}
}
}
template <typename T>
void postorder(node<T>* _node, void(*action)(T))
{
node<T>* nptr = _node;
bool ldsw = false;
while (nptr != nullptr) {
if (!ldsw) {
while (nptr->left != nullptr) {
if (nptr->left != nullptr) {
if (nptr->right != nullptr) {
nptr->left->next = nptr->right;
}
else {
nptr->left->next = nptr;
}
}
if (nptr->right != nullptr) {
nptr->right->next = nptr;
}
nptr = nptr->left;
}
if (nptr->left == nullptr && nptr->right != nullptr) {
if (nptr->left != nullptr) {
if (nptr->right != nullptr) {
nptr->left->next = nptr->right;
}
else {
nptr->left->next = nptr;
}
}
if (nptr->right != nullptr) {
nptr->right->next = nptr;
}
nptr = nptr->right;
}
ldsw = true;
}
if (nptr->left != nullptr && ldsw == true) {
action(nptr->data);
nptr = nptr->next;
ldsw = false;
if (nptr != nullptr && nptr->next == nullptr) {
action(nptr->data);
break;
}
}
else {
action(nptr->data);
nptr = nptr->next;
}
}
}
template <typename T>
class BinaryTree
{
node<T>* rootNode;
private:
public:
//노드 포인터를 리턴하는 함수
node<T>* getRoot();
node<T>* getRight(node<T>* node);
node<T>* getLeft(node<T>* node);
//src트리를 Dest노드의 자식으로 붙임
bool connectLeft(node<T>* DestNode, node<T>* SrcTree);
bool connectRight(node<T>* DestNode, node<T>* SrcTree);
public:
BinaryTree(T data);
virtual ~BinaryTree();
};
template <typename T>
BinaryTree<T>::BinaryTree(T data)
{
rootNode = new node<T>;
rootNode->data = data;
rootNode->left = nullptr;
rootNode->right = nullptr;
rootNode->prev = nullptr;
rootNode->next = nullptr;
}
template <typename T>
node<T>* BinaryTree<T>::getRoot()
{
return rootNode;
}
template <typename T>
node<T>* BinaryTree<T>::getLeft(node<T>* node)
{
return node->left;
}
template <typename T>
node<T>* BinaryTree<T>::getRight(node<T>* node)
{
return node->right;
}
template <typename T>
bool BinaryTree<T>::connectLeft(node<T>* DestNode, node<T>* srcTree)
{
if (DestNode->left == nullptr) {
DestNode->left = srcTree;
return true;
}
return false;
}
template <typename T>
bool BinaryTree<T>::connectRight(node<T>* DestNode, node<T>* srcTree)
{
if (DestNode->right == nullptr) {
DestNode->right = srcTree;
return true;
}
return false;
}
template <typename T>
BinaryTree<T>::~BinaryTree()
{
}반응형