포트폴리오

c++ binary Search Tree

윈우 2019. 10. 28. 06:18

스마트 포인터를 이용한 Binary Search Tree 구현

#pragma once

#include <memory>

namespace assignment4
{
	template<typename T>
	class TreeNode final
	{
	public:
		TreeNode(std::unique_ptr<T> data);
		TreeNode(std::shared_ptr<TreeNode<T>> parent, std::unique_ptr<T> data);

		std::unique_ptr<T> Data;
		std::shared_ptr<TreeNode<T>> Left;
		std::shared_ptr<TreeNode<T>> Right;
		std::weak_ptr<TreeNode<T>> Parent;
	private :
	};

	template<typename T>TreeNode<T>::TreeNode(std::unique_ptr<T> data)
		: Data(std::move(data))
	{
	}

	template<typename T>TreeNode<T>::TreeNode(std::shared_ptr<TreeNode<T>> parent, std::unique_ptr<T> data)
		: Parent(parent)
		, Data(std::move(data))
	{
	}
}
#pragma once

#include <memory>
#include <vector>

namespace assignment4
{
	template<typename T>
	class TreeNode;

	template<typename T>
	class BinarySearchTree final
	{
	public:
		void Insert(std::unique_ptr<T> data);
		bool Search(const T& data);
		bool Delete(const T& data);
		const std::weak_ptr<TreeNode<T>> GetRootNode() const;

		static std::vector<T> TraverseInOrder(const std::shared_ptr<TreeNode<T>> startNode);
	private:
		void insert(std::shared_ptr<TreeNode<T>> node, std::unique_ptr<T> data);
		std::shared_ptr<TreeNode<T>> search(std::shared_ptr<TreeNode<T>> node, const T& data) const;
		void changeParent(std::shared_ptr<TreeNode<T>> deleteNode, std::shared_ptr<TreeNode<T>> changeNode);
		std::shared_ptr<TreeNode<T>> mRoot;

	};

	template<typename T>
	void BinarySearchTree<T>::Insert(std::unique_ptr<T> data)
	{
		if (mRoot == nullptr)
		{
			std::shared_ptr<TreeNode<T>> node = std::make_shared<TreeNode<T>>(std::move(data));
			mRoot = node;
			return;
		}

		insert(mRoot, std::move(data));
	}
	template<typename T>
	void BinarySearchTree<T>::insert(std::shared_ptr<TreeNode<T>> parentNode, std::unique_ptr<T> data)
	{
		if (*data <= *parentNode->Data)
		{
			// left
			if (parentNode->Left == nullptr)
			{
				parentNode->Left = std::make_shared<TreeNode<T>>(parentNode, std::move(data));
			}
			else
			{
				insert(parentNode->Left, std::move(data));
			}
		}
		else
		{
			// right
			if (parentNode->Right == nullptr)
			{
				parentNode->Right = std::make_shared<TreeNode<T>>(parentNode, std::move(data));
			}
			else
			{
				insert(parentNode->Right, std::move(data));
			}
		}
	}

	template<typename T>
	const std::weak_ptr<TreeNode<T>> BinarySearchTree<T>::GetRootNode() const
	{
		return mRoot;
	}

	template<typename T>
	bool BinarySearchTree<T>::Search(const T& data)
	{
		std::shared_ptr<TreeNode<T>> node = search(mRoot, data);
		return node != nullptr;
	}

	template<typename T>
	std::shared_ptr<TreeNode<T>> BinarySearchTree<T>::search(std::shared_ptr<TreeNode<T>> node, const T& data) const
	{
		if (node == nullptr)
			return nullptr;

		if (*node->Data == data)
		{
			return node;
		}
		else if (data < *node->Data)
		{
			return search(node->Left, data);
		}
		else if (data > * node->Data)
		{
			return search(node->Right, data);
		}
	}

	template<typename T>
	bool BinarySearchTree<T>::Delete(const T& data)
	{
		std::shared_ptr<TreeNode<T>> node = search(mRoot, data);
		if (node == nullptr)
			return false;

		if (node->Left != nullptr && node->Right != nullptr)
		{
			std::shared_ptr<TreeNode<T>> sucecessorNode = node->Right;

			while (true)
			{
				if (sucecessorNode->Left == nullptr)
					break;

				sucecessorNode = sucecessorNode->Left;
			}

			changeParent(sucecessorNode, sucecessorNode->Right);
			changeParent(node, sucecessorNode);
			sucecessorNode->Left = node->Left;
			sucecessorNode->Right = node->Right;

			if (sucecessorNode->Left != nullptr)
			{
				sucecessorNode->Left->Parent = sucecessorNode;
			}
			if (sucecessorNode->Right != nullptr)
			{
				sucecessorNode->Right->Parent = sucecessorNode;
			}
		}
		else if (node->Left != nullptr)
		{
			changeParent(node, node->Left);
		}
		else if (node->Right != nullptr)
		{
			changeParent(node, node->Right);
		}
		else
		{
			changeParent(node, nullptr);
		}

		return true;
	}

	template<typename T>
	void BinarySearchTree<T>::changeParent(std::shared_ptr<TreeNode<T>> deleteNode, std::shared_ptr<TreeNode<T>> changeNode)
	{
		std::shared_ptr<TreeNode<T>> parent = deleteNode->Parent.lock();
		if (parent == nullptr)
		{
			mRoot = changeNode;
			return;
		}

		if (changeNode == nullptr)
		{
			if (parent->Left == deleteNode)
			{
				parent->Left = nullptr;
			}
			else if (parent->Right == deleteNode)
			{
				parent->Right = nullptr;
			}
		}
		else
		{
			if (parent->Left == deleteNode)
			{
				parent->Left = changeNode;
			}
			else if (parent->Right == deleteNode)
			{
				parent->Right = changeNode;
			}
			changeNode->Parent = deleteNode->Parent;
		}
	}

	template<typename T>
	std::vector<T> BinarySearchTree<T>::TraverseInOrder(const std::shared_ptr<TreeNode<T>> startNode)
	{
		std::vector<T> v;

		if (startNode == nullptr)
			return v;

		if (startNode->Left != nullptr)
		{
			v = TraverseInOrder(startNode->Left);
		}

		v.push_back(*startNode->Data);

		if (startNode->Right != nullptr)
		{
			std::vector<T> vR = TraverseInOrder(startNode->Right);
			v.insert(v.end(), vR.begin(), vR.end());
		}

		return v;
	}
}