08/18

이우석·2023년 8월 18일
0

SBS 국기수업

목록 보기
20/120

바이너리 서치 트리
Binary Tree에서 두 개의 추가적인 조건을 만족한 경우 이를 Binary Search Tree(이진 탐색 트리)라고 한다.

탐색 시
Root 부터 탐색한다
현재 방문한 Node의 key 값에 따라 다음 탐색 방향이 정해진다.
원하는 값을 찾지 못했다면 해당 Key값이 존재하지 않는 것

값 삽입
바이너리 트리와 동일

값 제거
삭제할 노드의 Left에 있는 노드 중 가장 큰 값(가장 오른쪽에 있는 값)을 찾는다. 그 값으로 삭제할 노드의 자리를 채운다.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace LearnAlgorithm_DataStructure
{
	public class bsNode<K, V> where K : IComparable
	{
		public K Key;
		public V Value;
		public bsNode<K, V> Parent, Left, Right;

		public bsNode()
		{
			Value = default(V);
			Parent = Left = Right = default(bsNode<K, V>);
		}

		public bsNode(K key, V value)
		{
			Key = key;
			Value = value;
			Parent = Left = Right = default(bsNode<K, V>);
		}

		public bsNode(K key, V value, bsNode<K, V> parent)
		{
			Key = key;
			Value = value;
			Parent = parent;
			Left = Right = default(bsNode<K, V>);
		}
	}

	class MyBinarySearchTree<K, V> where K : IComparable
	{
		private bsNode<K, V> Root;
		public int Count { get; private set; }

		public MyBinarySearchTree()
		{
			Root = null;
			Count = 0;
		}

		public bool Add(K key, V value)
		{
			if (Root == null)
			{
				Root = new bsNode<K, V>(key, value);
				Count++;
				return true;
			}

			return Add(key, value, Root);
		}

		// 재귀용
		private bool Add(K key, V value, bsNode<K, V> parentNode)
		{
			if (key.CompareTo(parentNode.Key) == 0)
			{
				Console.WriteLine($"Add : 동일한 키 값({key})이 입력되었습니다.");
				return false;
			}

			if (key.CompareTo(parentNode.Key) < 0)
			{
				if (parentNode.Left == default(bsNode<K, V>))
				{
					parentNode.Left = new bsNode<K, V>(key, value, parentNode);
					Count++;
					return true;
				}

				return Add(key, value, parentNode.Left);
			}
			else if (key.CompareTo(parentNode.Key) > 0)
			{
				if (parentNode.Right == default(bsNode<K, V>))
				{
					parentNode.Right = new bsNode<K, V>(key, value, parentNode);
					Count++;
					return true;
				}

				return Add(key, value, parentNode.Right);
			}

			Console.WriteLine("Add : 알 수 없는 오류입니다.");
			return false;
		}

		public bool Remove(K key)
		{
			bsNode<K, V> removeNode = Find(key, Root);

            if (IsEmptyNode(removeNode) == true)
            {
                Console.WriteLine("Remove : 삭제할 노드가 존재하지 않습니다.");
				return false;
			}

			return Remove(ref removeNode);
		}

		private bool Remove(ref bsNode<K, V> node)
		{
			if (IsEmptyNode(node) == false)
			{
				bsNode<K, V> parent = node.Parent; //지워질 노드의 parent 값을 저장해둠
				bsNode<K, V> left = node.Left; //지워질 노드의 left 값을 저장해둠
				bsNode<K, V> right = node.Right; //지워질 노드의 Right 값을 저장해둠

				if (IsEmptyNode(left) == false)
				{
					if (IsEmptyNode(left.Right) == false)
					{
						bsNode<K, V> LastRightOfLeft = left.Right; // 지워진 노드의 right를 연결할 left중 가장 오른쪽의 노드를 찾기

						while (IsEmptyNode(LastRightOfLeft.Right) == false)
						{
							LastRightOfLeft = LastRightOfLeft.Right;
						}

						node.Key = LastRightOfLeft.Key;
						node.Value = LastRightOfLeft.Value;
						LastRightOfLeft.Parent.Right = default;

						Count--;
						return true;
					}

					// IsEmptyNode(left.Right) == true
					node.Key = left.Key;
					node.Value = left.Value;
					node.Left = left.Left;

					Count--;
					return true;
				}

				// Right만 있는 경우에만 Right 쪽을 끌어올림
				if (IsEmptyNode(right) == false)
				{
					node.Key = right.Key;
					node.Value = right.Value;
					node.Left = right.Left;
					node.Right = right.Right;

					Count--;
					return true;
				}

				//Left도 Right도 없는 External Node인 경우, 부모와 자신의 연결만 끊음
				if (parent.Left.Equals(node))
				{
					node.Parent.Left = null;
					node.Parent = null;
					return true;
				}

				if (node.Parent.Right.Equals(node))
				{
					node.Parent.Right = null;
					node.Parent = null;
					return true;
				}
			}

			Console.WriteLine("Remove : 알 수 없는 오류가 발생했습니다.");
			return false;
		}

		public bsNode<K, V> Find(K key, bsNode<K, V> node)
		{
			if (key.CompareTo(node.Key) == 0)
			{
				return node;
			}

			if(key.CompareTo(node.Key) > 0 && IsEmptyNode(node.Right) == false)
			{
				return Find(key, node.Right);
			}

			if (key.CompareTo(node.Key) < 0 && IsEmptyNode(node.Left) == false)
			{
				return Find(key, node.Left);
			}

            Console.WriteLine("Find : 값이 존재하지 않습니다.");
			return null;
		}

		protected static bool IsEmptyNode(bsNode<K, V> node)
		{
			return node == default(bsNode<K, V>);
		}

		public void Print(bsNode<K, V> node = default, string locate = default)
		{
			if (node == default)
			{
				node = Root;
			}

			if (locate == default)
			{
				locate = "Root";
			}

			Console.Write($"({node.Key}, {node.Value})");
			Console.WriteLine(" : " + locate);

			if (IsEmptyNode(node.Left) == false)
			{
				Print(node.Left, locate + " L");
			}

			if (IsEmptyNode(node.Right) == false)
			{
				Print(node.Right, locate + " R");
			}
		}

		public bool IsEmpty()
		{
			return Count == 0;
		}
	}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace LearnAlgorithm_DataStructure
{
	internal class Program
	{
		static void Main()
		{
			//ArrayListTest();
			//LinkedListTest();
			//QueueTest();
			//StackTest();
			//QueueArrayTest();
			//StackArrayTest();
			//BinaryTreeTest();
			//BinarySearchTreeTest();
			BinarySearchTreeFileTest();


			Console.ReadKey();
		}

        static void BinarySearchTreeFileTest()
		{

		}

        static void BinarySearchTreeTest()
		{
			var bsTree = new MyBinarySearchTree<int, int>();
			Console.WriteLine("=== Add : 100, 50, 51, 49, 150, 151, 149 ===");
			bsTree.Add(100, 1);
			bsTree.Add(50, 2);
			bsTree.Add(51, 3);
			bsTree.Add(49, 4);
			bsTree.Add(150, 5);
			bsTree.Add(151, 6);
			bsTree.Add(149, 7);

			bsTree.Print();
			Console.WriteLine();

			Console.WriteLine("=== Remove : 100 ===");
			bsTree.Remove(100);
			bsTree.Print();
			Console.WriteLine();

			Console.WriteLine("=== Remove : 50 ===");
			bsTree.Remove(50);
			bsTree.Print();
			Console.WriteLine();

			Console.WriteLine("=== Remove : 150 ===");
			bsTree.Remove(150);
			bsTree.Print();
			Console.WriteLine();

			Console.WriteLine("=== Remove : 51 ===");
			bsTree.Remove(51);
			bsTree.Print();
		}

		static void BinaryTreeTest()
		{
			var binaryTree = new MyBinaryTree<int>();
			Console.WriteLine("=== Add : 100, 50, 200, 150, 99, 10, 250 ===");
			binaryTree.Add(100);
			binaryTree.Add(50);
			binaryTree.Add(200);
			binaryTree.Add(150);
			binaryTree.Add(10);
			binaryTree.Add(99);
			binaryTree.Add(250);

			binaryTree.Print();


			Console.WriteLine("=== Remove : 100 ===");
			binaryTree.Remove(100);
			binaryTree.Print();

			Console.WriteLine("=== Remove : 10 ===");
			binaryTree.Remove(10);
			binaryTree.Print();

			Console.WriteLine("=== Remove : 200 ===");
			binaryTree.Remove(200);
			binaryTree.Print();
		}

		static void StackTest()
		{
			var myStack = new MyStack<string>();
			string first, second;
			Console.WriteLine("=== 값 3개 Push ===");
			myStack.Push("하나").Push("둘").Push("셋").Print();
			Console.WriteLine($"Size : {myStack.Size()}");
			Console.WriteLine();

			Console.WriteLine("=== 값 1개 Pop ===");
			first = myStack.Pop();
			Console.WriteLine($"Pop 결과 : {first}");
			myStack.Print();
			Console.WriteLine($"Size : {myStack.Size()}");
			Console.WriteLine();

			Console.WriteLine("=== 값 1개 Pop ===");
			myStack.Pop(out second);
			Console.WriteLine($"Pop 결과 : {second}");
			myStack.Print();
			Console.WriteLine($"Size : {myStack.Size()}");
			Console.WriteLine();

			Console.WriteLine("=== 값 3개 Push ===");
			myStack.Push("하나").Push("둘").Push("셋").Print();
			Console.WriteLine($"Size : {myStack.Size()}");
			Console.WriteLine();

			Console.WriteLine("=== 값 1개 Top ===");
			first = myStack.Top();
			Console.WriteLine($"Top 결과 : {first}");
			myStack.Print();
			Console.WriteLine($"Size : {myStack.Size()}");
			Console.WriteLine();

			Console.WriteLine("=== 값 1개 Top ===");
			myStack.Top(out second);
			Console.WriteLine($"Top 결과 : {second}");
			myStack.Print();
			Console.WriteLine($"Size : {myStack.Size()}");
			Console.WriteLine();

			Console.WriteLine("=== 값 1개 Pop ===");
			myStack.Pop(out second);
			Console.WriteLine($"Pop 결과 : {second}");
			myStack.Print();
			Console.WriteLine($"Size : {myStack.Size()}");
			Console.WriteLine();
		}

		static void StackArrayTest()
		{
			var myStack = new MyStackArray<string>();
			string first, second;
			Console.WriteLine("=== 값 3개 Push ===");
			myStack.Push("하나").Push("둘").Push("셋").Print();
			Console.WriteLine($"Size : {myStack.Size()}");
			Console.WriteLine();

			Console.WriteLine("=== Pop ===");
			first = myStack.Pop();
			Console.WriteLine($"Pop 결과 : {first}");
			myStack.Print();
			Console.WriteLine($"Size : {myStack.Size()}");
			Console.WriteLine();

			Console.WriteLine("=== Pop ===");
			myStack.Pop(out second);
			Console.WriteLine($"Pop 결과 : {second}");
			myStack.Print();
			Console.WriteLine($"Size : {myStack.Size()}");
			Console.WriteLine();

			Console.WriteLine("=== 값 3개 Push ===");
			myStack.Push("하나").Push("둘").Push("셋").Print();
			Console.WriteLine($"Size : {myStack.Size()}");
			Console.WriteLine();

			Console.WriteLine("===  Top ===");
			first = myStack.Top();
			Console.WriteLine($"Top 결과 : {first}");
			myStack.Print();
			Console.WriteLine($"Size : {myStack.Size()}");
			Console.WriteLine();

			Console.WriteLine("=== Top ===");
			myStack.Top(out second);
			Console.WriteLine($"Top 결과 : {second}");
			myStack.Print();
			Console.WriteLine($"Size : {myStack.Size()}");
			Console.WriteLine();

			Console.WriteLine("=== Pop ===");
			myStack.Pop(out second);
			Console.WriteLine($"Pop 결과 : {second}");
			myStack.Print();
			Console.WriteLine($"Size : {myStack.Size()}");
			Console.WriteLine();
		}

		static void QueueTest()
		{
			var myQueue = new MyQueue<int>();
			int first, second;
			Console.WriteLine("=== 값 3개 EnQueue ===");
			myQueue.EnQueue(1).EnQueue(2).EnQueue(3).Print();
			Console.WriteLine($"Size : {myQueue.Size()}");
			Console.WriteLine();

			Console.WriteLine("=== DeQueue ===");
			first = myQueue.DeQueue();
			Console.WriteLine($"DeQueue 결과 : {first}");
			myQueue.Print();
			Console.WriteLine($"Size : {myQueue.Size()}");
			Console.WriteLine();

			Console.WriteLine("=== DeQueue ===");
			myQueue.DeQueue(out second);
			Console.WriteLine($"DeQueue 결과 : {second}");
			myQueue.Print();
			Console.WriteLine($"Size : {myQueue.Size()}");
			Console.WriteLine();

			Console.WriteLine("=== 값 3개 EnQueue ===");
			myQueue.EnQueue(1).EnQueue(2).EnQueue(3).Print();
			Console.WriteLine($"Size : {myQueue.Size()}");
			Console.WriteLine();

			Console.WriteLine("=== Front ===");
			first = myQueue.Front();
			Console.WriteLine($"Front 결과 : {first}");
			myQueue.Print();
			Console.WriteLine($"Size : {myQueue.Size()}");
			Console.WriteLine();

			Console.WriteLine("=== Front ===");
			myQueue.Front(out second);
			Console.WriteLine($"Front 결과 : {second}");
			myQueue.Print();
			Console.WriteLine($"Size : {myQueue.Size()}");
			Console.WriteLine();

			Console.WriteLine("=== DeQueue ===");
			myQueue.DeQueue(out second);
			Console.WriteLine($"DeQueue 결과 : {second}");
			myQueue.Print();
			Console.WriteLine($"Size : {myQueue.Size()}");
			Console.WriteLine();
		}

		static void QueueArrayTest()
		{
			var myQueue = new MyQueue<int>();
			int first, second;
			Console.WriteLine("=== 값 3개 EnQueue ===");
			myQueue.EnQueue(1).EnQueue(2).EnQueue(3).Print();
			Console.WriteLine($"Size : {myQueue.Size()}");
			Console.WriteLine();

			Console.WriteLine("=== DeQueue ===");
			first = myQueue.DeQueue();
			Console.WriteLine($"DeQueue 결과 : {first}");
			myQueue.Print();
			Console.WriteLine($"Size : {myQueue.Size()}");
			Console.WriteLine();

			Console.WriteLine("=== DeQueue ===");
			myQueue.DeQueue(out second);
			Console.WriteLine($"DeQueue 결과 : {second}");
			myQueue.Print();
			Console.WriteLine($"Size : {myQueue.Size()}");
			Console.WriteLine();

			Console.WriteLine("=== 값 3개 EnQueue ===");
			myQueue.EnQueue(1).EnQueue(2).EnQueue(3).Print();
			Console.WriteLine($"Size : {myQueue.Size()}");
			Console.WriteLine();

			Console.WriteLine("=== Front ===");
			first = myQueue.Front();
			Console.WriteLine($"Front 결과 : {first}");
			myQueue.Print();
			Console.WriteLine($"Size : {myQueue.Size()}");
			Console.WriteLine();

			Console.WriteLine("=== Front ===");
			myQueue.Front(out second);
			Console.WriteLine($"Front 결과 : {second}");
			myQueue.Print();
			Console.WriteLine($"Size : {myQueue.Size()}");
			Console.WriteLine();

			Console.WriteLine("=== DeQueue ===");
			myQueue.DeQueue(out second);
			Console.WriteLine($"DeQueue 결과 : {second}");
			myQueue.Print();
			Console.WriteLine($"Size : {myQueue.Size()}");
			Console.WriteLine();
		}

		static void LinkedListTest()
		{
			var myLinkedList = new MyLinkedList<object>();
			Console.WriteLine("=== 값 3개 Add ===");
			myLinkedList.Add(1);
			myLinkedList.Add(2);
			myLinkedList.Add(3);
			myLinkedList.Print();
			Console.WriteLine();

			Console.WriteLine("=== Get, Set ===");
			Console.Write("GET : myLinkedList[1] = ");
			Console.WriteLine(myLinkedList[1]);
			Console.WriteLine("SET : myLinkedList[1] = 4;");
			myLinkedList[1] = 4;
			myLinkedList.Print();
			Console.WriteLine();

			Console.WriteLine("=== Insert(0, 5) ===");
			myLinkedList.Insert(0, 5);
			myLinkedList.Print();
			Console.WriteLine();

			Console.WriteLine("=== Insert(2, 5) ===");
			myLinkedList.Insert(2, 5);
			myLinkedList.Print();
			Console.WriteLine();

			Console.WriteLine("=== Insert(4, 5) ===");
			myLinkedList.Insert(4, 5);
			myLinkedList.Print();
			Console.WriteLine();

			Console.WriteLine("=== Remove(5) ===");
			myLinkedList.Remove(5);
			myLinkedList.Print();
			Console.WriteLine();

			Console.WriteLine("=== Remove(0) ===");
			myLinkedList.Remove(0);
			myLinkedList.Print();
			Console.WriteLine();

			Console.WriteLine("=== Remove(3) ===");
			myLinkedList.Remove(3);
			myLinkedList.Print();
			Console.WriteLine();

			Console.WriteLine("=== Remove(1) ===");
			myLinkedList.Remove(1);
			myLinkedList.Print();
			Console.WriteLine();
		}

		static void ArrayListTest()
		{
			try
			{
				{
					var myArrayList = new MyArrayList<string>();

					Console.WriteLine("===== Count =====");
					myArrayList.test();
					Console.WriteLine($"IsEmpty : {myArrayList.IsEmpty}");
					Console.WriteLine();
					Console.WriteLine();

					Console.WriteLine("===== 1개 값 Add =====");
					myArrayList.Add("하나");
					myArrayList.test();
					Console.WriteLine($"IsEmpty : {myArrayList.IsEmpty}");
					Console.WriteLine();
					Console.WriteLine();

					Console.WriteLine("===== 7개 값 Add =====");
					myArrayList.Add("둘");
					myArrayList.Add("둘");
					myArrayList.Add("둘");
					myArrayList.Add("둘");
					myArrayList.Add("둘");
					myArrayList.Add("둘");
					myArrayList.Add("둘");
					myArrayList.test();
					Console.WriteLine();
					Console.WriteLine();

					// 8개 이후
					Console.WriteLine("===== 4개 값 Add =====");
					myArrayList.Add("셋");
					myArrayList.Add("셋");
					myArrayList.Add("셋");
					myArrayList.Add("셋");
					myArrayList.test();
					Console.WriteLine();
					Console.WriteLine();

					Console.WriteLine("===== Insert(0, \"넷\"); =====");
					myArrayList.Insert(0, "넷");
					myArrayList.test();
					Console.WriteLine();
					Console.WriteLine();

					Console.WriteLine("===== Insert(3, \"넷\"); =====");
					myArrayList.Insert(3, "넷");
					myArrayList.test();
					Console.WriteLine();
					Console.WriteLine();

					Console.WriteLine("===== Insert(-1, \"넷\"); =====");
					myArrayList.Insert(-1, "넷");
					myArrayList.test();
					Console.WriteLine();
					Console.WriteLine();

					Console.WriteLine("===== Insert(100, \"넷\"); =====");
					myArrayList.Insert(100, "넷");
					myArrayList.test();
					Console.WriteLine();
					Console.WriteLine();

					Console.WriteLine("===== Remove(0); =====");
					myArrayList.Remove(0);
					myArrayList.test();
					Console.WriteLine();
					Console.WriteLine();

					Console.WriteLine("===== Remove(11); =====");
					myArrayList.Remove(11);
					myArrayList.test();
					Console.WriteLine();
					Console.WriteLine();

					Console.WriteLine("===== Remove(20); =====");
					myArrayList.Remove(20);
					myArrayList.test();
					Console.WriteLine();
					Console.WriteLine();

					Console.WriteLine("===== GET myArrayList[0] =====");
					Console.WriteLine(myArrayList[0]);
					myArrayList.test();
					Console.WriteLine();
					Console.WriteLine();

					Console.WriteLine("===== SET myArrayList[0] = \"하나둘셋\" =====");
					Console.WriteLine(myArrayList[0] = "하나둘셋");
					myArrayList.test();
					Console.WriteLine();
					Console.WriteLine();
				}
			}
			catch (Exception ex)
			{
				Console.WriteLine(ex.ToString());
			}
		}
	}
}
profile
게임 개발자 지망생, 유니티 공부중!

0개의 댓글