Study/Data Structure

[Data Structure] Tree C++로 만들기

wnwnovo 2024. 10. 10. 08:44
#include <iostream>
#include <string>
#include <list>
#include <vector>
#include <cmath>
using namespace std;

struct Node
{
	int value;
	int depth;
	Node* child[2];                     // 0 - left, 1 - right
	int sibiling;						// 같은 depth에서 좌측부터 부여된 index

	Node()
	{
		depth = 0;
		value = 0;
		sibiling = 0;
		child[0] = child[1] = NULL;
	}
};

Node* root = NULL;

bool valueComp(Node* i, Node* j)
{
	return	i->value < j->value;
}

bool DepthComp(Node* i, Node* j)
{
	return	i->depth < j->depth;
}

void CollectTreeNode(std::list<Node*>& listNode, Node* node, Node* parent, int childIndex)
{
	if (parent)
	{
		node->sibiling = parent->sibiling * 2 + childIndex;
	}
	else
	{
		node->sibiling = 0;
	}

	listNode.push_back(node);

	for (int i = 0; i < 2; ++i)
	{
		if (node->child[i])
		{
			CollectTreeNode(listNode, node->child[i], node, i);
		}
	}
}

void ConstructTree(std::list<Node*>& listNode, Node* parent, int childIndex)
{
	int listLen = listNode.size();

	int halfIndex = listLen / 2;
	Node* nwCenter = NULL;
	std::list<Node*> listLeft;
	std::list<Node*> listRight;

	int i = 0;
	std::list<Node*>::iterator itor_node = listNode.begin();
	while (itor_node != listNode.end())
	{
		Node* n = *itor_node;
		if (i < halfIndex)
		{
			listLeft.push_back(*itor_node);
		}
		else if (i == halfIndex)
		{
			nwCenter = *itor_node;
			if (parent == NULL)
			{
				root = nwCenter;
				nwCenter->depth = 0;
			}
			else
			{
				int index = nwCenter->value > parent->value ? 1 : 0;
				int index2 = 1 - index;
				parent->child[index] = nwCenter;
				nwCenter->depth = parent->depth + 1;
			}
		}
		else
		{
			listRight.push_back(*itor_node);
		}

		++i;
		++itor_node;
	}

	if (listLeft.size() > 0)
	{
		ConstructTree(listLeft, nwCenter, 0);
	}
	if (listRight.size() > 0)
	{
		ConstructTree(listRight, nwCenter, 1);
	}
}

void RearrangeTree()
{
	std::list<Node*> listNode;
	CollectTreeNode(listNode, root, NULL, 0);
	listNode.sort(valueComp);

	list<Node*>::iterator itr = listNode.begin();
	while (itr != listNode.end())
	{
		Node* node = *itr;
		node->child[0] = NULL;
		node->child[1] = NULL;
		itr++;
	}

	ConstructTree(listNode, NULL, 0);
}

void AddNodeToTree(Node* parent, Node* node)
{
	if (parent == NULL)
	{
		root = node;
		return;
	}

	int addIndex = node->value > parent->value ? 1 : 0;
	if (parent->child[addIndex] == NULL)
	{
		parent->child[addIndex] = node;
		node->depth = parent->depth + 1;
		RearrangeTree();
	}
	else
	{
		AddNodeToTree(parent->child[addIndex], node);
	}
}

void RemoveNodeFromTree(int val, Node* parent, int childIndex, Node* node)
{
	if (node == NULL) return;

	if (node->value == val)
	{
		if (node->child[0] == NULL && node->child[1] == NULL)
		{
			if (parent == NULL)
			{
				root = NULL;
				return;
			}
			else
			{
				parent->child[childIndex] = NULL;
				// tree depth 갱신

				return;
			}
		}
		else
		{
			std::list<Node*> listNode;
			CollectTreeNode(listNode, root, NULL, 0);
			
			list<Node*>::iterator iter = listNode.begin();
			while (iter != listNode.end())
			{
				Node* pNode = *iter;
				if (pNode->value == val)
				{
					listNode.erase(iter);
					break;
				}
				++iter;
			}

			iter = listNode.begin();
			while (iter != listNode.end())
			{
				Node* node = *iter;
				node->child[0] = NULL;
				node->child[1] = NULL;
				iter++;
			}

			listNode.sort(valueComp);
			ConstructTree(listNode, NULL, 0);
		}
	}
	else
	{
		int index = node->value < val ? 1 : 0;
		RemoveNodeFromTree(val, node, index, node->child[index]);
	}
}

Node* FindNodeByValue(int val, Node* node)
{
	if (node->value == val)
	{
		return node;
	}

	int index = node->value < val ? 1 : 0;
	Node* childNode = node->child[index];
	if (childNode == NULL)
	{
		return NULL;
	}
	else
	{
		return FindNodeByValue(val, childNode);
	}
}

void RemoveNodeByKeyFromTree(int val)
{
	RemoveNodeFromTree(val, NULL, 0, root);
}

Node* FindParentNode(Node* childNode, Node* parentNode)
{
	int index = childNode->value > parentNode->value ? 1 : 0;
	if (parentNode->child[index] == childNode)
	{
		return parentNode;
	}
	if (childNode == parentNode)
	{
		return NULL;
	}
	FindParentNode(childNode, parentNode->child[index]);
}

void DisplayTree()
{
	std::list<Node*> listNode;
	CollectTreeNode(listNode, root, NULL, 0);
	listNode.sort(DepthComp);

	int maxDepth = listNode.back()->depth;
	vector<vector<Node*>> vecDepthVectors(maxDepth+1);
	//vecDepthVectors.reserve(maxDepth);
	for (int i = 0; i < maxDepth+1; ++i)
	{
		size_t capacity = pow(2, i);
		vecDepthVectors[i].reserve(capacity);
		vecDepthVectors[i].assign(capacity, NULL);

	}

	std::list<Node*>::iterator iter = listNode.begin();
	while (iter != listNode.end())
	{
		Node* pNode = *iter;
		int sibling = pNode->sibiling;
		vector<Node*>::iterator itr = (vecDepthVectors[pNode->depth].begin() + sibling);
		vecDepthVectors[pNode->depth].insert(itr, pNode);
		++iter;
	}

	printf("\n[Root]\n");
	

	for (int depth = 0; depth <= maxDepth; ++depth)
	{
		int maxSibling = pow(2, depth);
		// 시작 space 출력
		int tab = maxDepth - depth;
		for (int i = 0; i < tab; i++)
		{
			printf("   ");
		}

		for (int sibiling = 0; sibiling < maxSibling; ++sibiling)
		{
			Node* pNode = vecDepthVectors[depth][sibiling];
			if (pNode)
			{
				printf("[%03d]", pNode->value);		// 001
			}
			else
			{
				printf("   ");
			}

			if (sibiling % 2 == 0)
			{
				// sibilng 간 space 출력 (작게)
				for (int i = 0; i < tab; i++)
				{
					printf("   ");
				}
			}
			else
			{
				// sibilng 간 space 출력 (크게)
				for (int i = 0; i < tab; i++)
				{
					printf(" ");
				}

			}
		}
		printf("\n");
	}
}

int main()
{
	const int size = 20;
	printf("Size : %d\n", size);

	Node* nodes[size];
	for (int i = 0; i < size; ++i)
	{
		Node* N = new Node;
		N->value = i;
		AddNodeToTree(root, N);
		nodes[i] = N;
	}

	RemoveNodeByKeyFromTree(4);
	DisplayTree();

	RemoveNodeByKeyFromTree(10);
	DisplayTree();

	getchar();
}

'Study > Data Structure' 카테고리의 다른 글

[Data Structure] HashTable C++로 만들기  (0) 2024.10.10
[Data Structure] List C++로 만들기  (0) 2024.10.10