0401 이진탐색트리Binary Search Tree

2021. 4. 1. 18:24C#/자료구조

왼쪽 노드의 값이 루트 노드의 값보다 작고,  (root>node)=left
오른쪽 노드의 값이 루트 노드의 값보다 큰 값을 갖는 트리 (root<node)=right
모든 노드의 키가 unique 하다는 정의를 포함시키는 것이 일반적
중복을 허용하는 트리의 경우 왼쪽 서브트리는 루트보다 작거나 같고,
오른쪽 서브트리는 루트보다 크거나 같다

 public class BSTNode
    {
        public int data;
        public BSTNode left;
        public BSTNode right;
        public BSTNode(int data) 
        {
            this.data = data;
        }
    }
public class BinarySearchTree
    {
        private BSTNode root;
        public BinarySearchTree() 
        {
            
        }
        public void Add(int data) 
        {
            if (root == null) 
            {
                this.root = new BSTNode(data);
                return;
            }

            //비교
            var node = this.root;
            while (node != null) 
            {
                //추가 하려는 값과 노드의 값을 비교
                var result = data.CompareTo(node.data);

                if (result == 0)
                {
                    //같다
                    throw new ApplicationException("duplicate");
                }
                else if (result < 0)
                {
                    //작다
                    if (node.left == null)
                    {
                        node.left = new BSTNode(data);
                        break;
                    }
                    else
                    {
                        node = node.left;
                    }
                }
                else 
                {
                    //크다 
                    if (node.right == null)
                    {
                        node.right = new BSTNode(data);
                        break;
                    }
                    else
                    {
                        node = node.right;
                    }
                }
            }
        }
    }
public class App
    {
        public App()
        {
            BinarySearchTree tree = new BinarySearchTree();
            tree.Add(10);
        }
    }

 

    public class BinarySearchTree
    {
        private BSTNode root;
        public BinarySearchTree() 
        {
            
        }
        public void Add(int data) 
        {
            if (root == null) 
            {
                this.root = new BSTNode(data);
                return;
            }

            //비교
            var node = this.root;
            while (node != null) 
            {
                //추가 하려는 값과 노드의 값을 비교
                var result = data.CompareTo(node.data);

                if (result == 0)
                {
                    //같다
                    throw new ApplicationException("duplicate");
                }
                else if (result < 0)
                {
                    //작다
                    if (node.left == null)
                    {
                        node.left = new BSTNode(data);
                        break;
                    }
                    else
                    {
                        node = node.left;
                    }
                }
                else 
                {
                    //크다 
                    if (node.right == null)
                    {
                        node.right = new BSTNode(data);
                        break;
                    }
                    else
                    {
                        node = node.right;
                    }
                }
            }
        }
        public bool Search(int data) 
        {
            var node = this.root;
            while (node != null)
            {
                //넣은 값과 노드 값을 비교
                var result=data.CompareTo(node.data);
                if (result == 0)
                {
                    //넣은 값과 노드 값이 같으면 true
                    return true;
                }
                else if (result > 0)
                {
                    //넣은 값>노드면 오른쪽
                    node = node.right;
                }
                else if (result < 0) 
                {
                    //넣은 값<노드면 왼쪽
                    node = node.left;
                }
            }
            //다 돌았는데도 없으면
            return false;
        }
    }
 public class App
    {
        public App()
        {
            BinarySearchTree tree = new BinarySearchTree();
            tree.Add(10);
            var result=tree.Search(10);
            Console.WriteLine(result);
        }
    }

 

재귀함수로 구현한 search 메서드

public class BinarySearchTree
    {
        private BSTNode root;
        public BinarySearchTree() 
        {
            
        }
        public void Add(int data) 
        {
            if (root == null) 
            {
                this.root = new BSTNode(data);
                return;
            }

            //비교
            var node = this.root;
            while (node != null) 
            {
                //추가 하려는 값과 노드의 값을 비교
                var result = data.CompareTo(node.data);

                if (result == 0)
                {
                    //같다
                    throw new ApplicationException("duplicate");
                }
                else if (result < 0)
                {
                    //작다
                    if (node.left == null)
                    {
                        node.left = new BSTNode(data);
                        break;
                    }
                    else
                    {
                        node = node.left;
                    }
                }
                else 
                {
                    //크다 
                    if (node.right == null)
                    {
                        node.right = new BSTNode(data);
                        break;
                    }
                    else
                    {
                        node = node.right;
                    }
                }
            }
        }
        //재귀함수
        public bool SearchRecursive(int data) 
        {
            return SearchRecursive(this.root, data);
        }
        public bool SearchRecursive(BSTNode node, int data) 
        {
            var result=data.CompareTo(node.data);
            if (result == 0) 
            {
                return true;
            }
            return SearchRecursive(node.left, data) || SearchRecursive(node.right, data);
        }
public class App
    {
        public App()
        {
            BinarySearchTree tree = new BinarySearchTree();
            tree.Add(10);
            //var result=tree.Search(10);
            var result = tree.SearchRecursive(10);
            Console.WriteLine(result);
        }
    }

 

자식 노드가 1개면
부모 노드에서 삭제할 노드 자리에 왼쪽/오른쪽 자식 노드를 대입한다.
자식 노드가 2개면
왼쪽 서브트리 중 가장 큰 수/오른쪽 서브트리 중 가장 작은 수를 
삭제할 노드 자리에 옮긴다.

오른쪽 서브트리의 가장 작은 값= minNode

 public class BinarySearchTree
    {
        private BSTNode root;
        public BinarySearchTree() 
        {
            
        }
        public bool Remove(int data) 
        {
            var node = this.root;
            BSTNode prev = null;

            while (node != null) 
            {
                var result = data.CompareTo(node.data);
                if (result == 0)
                {
                    break;
                }
                else if (result < 0)
                {
                    prev = node;
                    node = node.left;
                }
                else 
                {
                    prev = node;
                    node = node.right;
                }
            }
            if (node == null) return false;

            //노드를 찾음 (삭제 진행)
            //1.왼쪽 노드 or 오른쪽 노드가 없는 경우
            if (node.left == null && node.right == null)
            {
                //부모에서 떼어내기
                if (prev.left == node)
                {
                    prev.left = null;
                }
                else
                {
                    prev.right = null;
                }
                //찾으려고 하는 노드를 null로 만듦.
                node = null;
            }
            //2.노드의 왼쪽/오른쪽이 있으면
            else if (node.left != null || node.right != null)
            {
                //왼쪽/오른쪽 둘 하나만 있는 경우
                var child = node.left != null ? node.left : node.right;
                if (prev.left == node)
                {
                    prev.left = child;
                }
                else 
                {
                    prev.right = child;
                }
            }
            else 
            {
                //왼쪽 오른쪽 둘 다 있는 경우
                //검색된 노드 저장
                var pre = node;
                //검색된 노드의 오른쪽 노드 저장
                var min = node.right;

                while (min.left != null) 
                {
                    pre = min;
                    min = min.left;
                }
                node.data = min.data;
                if (pre.left == min)
                {
                    pre.left = min.right;
                }
                else 
                {
                    pre.right = min.right;
                }
                

            }
            return true;
        }
        
public class App
    {
        public App()
        {
            BinarySearchTree tree = new BinarySearchTree();
            tree.Add(30);
            tree.Add(25);
            tree.Add(35);
            tree.Add(21);
            tree.Add(27);
            tree.Add(28);
            //var result=tree.Search(10);
            //var result = tree.SearchRecursive(10);
            var result = tree.Remove(25);
            Console.WriteLine(result);
        }
    }