유니티3D 프로그래밍

C# 4주차 5일 수업 내용 : Tree 복습 2, Graph (21.04.02) 본문

C#/자료구조

C# 4주차 5일 수업 내용 : Tree 복습 2, Graph (21.04.02)

tjdgus9955 2021. 4. 2. 12:13

Binary Search Tree

 

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

namespace Study02
{
    public class App
    {
        //생성자 
        public App()
        {
            Console.WriteLine("App");
            BST bst = new BST();
            bst.Add(30);
            bst.Add(25);
            bst.Add(35);
            bst.Add(21);
            bst.Add(19);
            bst.Add(23);

            var target = 25;
            Console.WriteLine("target: {0}", target);
            var result = bst.Search(target);
            Console.WriteLine("result: {0}", result);
            Console.WriteLine();
            target = 50;
            Console.WriteLine("target: {0}", target);
            result = bst.Search(target);
            Console.WriteLine("result: {0}", result);
            bst.Remove(23);
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Study02
{
    public class BSTNode
    {
        public int data;
        public BSTNode left;
        public BSTNode right;
        //생성자 
        public BSTNode(int data)
        {
            this.data = data;
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Study02
{
    public class BST
    {
        private BSTNode root;

        //생성자 
        public BST()
        {

        }
        //추가 
        public void Add(int data)
        {
            if (this.root == null)
            {
                this.root = new BSTNode(data);
            }
            else
            {
                //변수에 루트 담기 
                var node = this.root;
                //변수의 값이 null아닐때까지 반복 
                while (node != null)
                {
                    //비교 
                    var result = data.CompareTo(node.data);

                    if (result == 0)
                    {
                        //같으면 값이 이미 있음 
                        throw new ApplicationException("duplicated!");
                    }
                    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;

            //변수의 값이 null아닐경우 반복 
            while (node != null)
            {
                //검색하는 데이터와 변수에 있는 노드의 값과 비교 
                var result = data.CompareTo(node.data);

                //만약에 같다면 true 반환 
                if (result == 0)
                {
                    return true;
                }
                else if (result < 0)
                {
                    //작다면 변수에 왼쪽 노드 넣기 
                    node = node.left;
                }
                else
                {
                    //크다면 변수에 오른족 노드 넣기 
                    node = node.right;
                }
            }

            //못찾았다면 false 반환 
            return false;
        }
        //삭제 
        public bool Remove(int data)
        {

            //삭제할 노드 찾기 

            //node변수에 루트 넣기 
            var node = this.root;
            BSTNode prev = null;

            //node변수가 null이 아닐때까지 반복 
            while (node != null)
            {
                //삭제할 데이터와 node변수의 값을 비교 
                var result = data.CompareTo(node.data);
                //같다 (찾았다)
                if (result == 0)
                {
                    break;
                }
                else if (result < 0)
                {
                    //작다면 node변수에 node의 왼쪽 노드를 넣는다.
                    prev = node;
                    node = node.left;
                }
                else
                {
                    //크다면 node변수에 node의 오른쪽 노드를 넣는다 
                    prev = node;
                    node = node.right;
                }
            }

            if (node != null)
            {
                Console.WriteLine("삭제하려고 하는 노드를 찾았습니다. {0}노드 ", node.data);
            }
            else
            {
                Console.WriteLine("삭제하려고 하는 노드를 못찾았습니다.");
                return false;
            }


            //타겟 노드의 왼쪽과 오른쪽 노드가 없는경우 
            if (node.left == null && node.right == null)
            {
                //부모노드의 왼쪽과 찾으려고 하는 노드가 같다면 
                if (prev.left == node)
                {
                    prev.left = null;    //부모노드의 왼쪽노드를 없앰 
                }
                else
                {
                    prev.right = null;  //부모노드의 오른쪽노드를 없앰 
                }
            }
            else if (node.left == null || node.right == null)
            {
                //자식이 1개 인경우 

                //child 변수 선언 (찾은 노드의 자식)
                //node의 왼쪽 노드가 있다면 왼쪽노드를 없다면 오른쪽 노드를 할당 
                var child = node.left != null ? node.left : node.right;

                //부모의 왼쪽 노드와 node 비교 
                if (prev.left == node)
                {
                    //같다면 부모의 왼쪽 노드에 child 할당 
                    prev.left = child;
                }
                else
                {
                    //다르다면 부모노드의 오른쪽 노드에 child 할당 
                    prev.right = child;
                }
            }


            return true;
        }
    }
}

 

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

namespace Study02
{
    public class BST
    {
        private BSTNode root;

        //생성자 
        public BST()
        {

        }
        //추가 
        public void Add(int data)
        {
            if (this.root == null)
            {
                this.root = new BSTNode(data);
            }
            else
            {
                //변수에 루트 담기 
                var node = this.root;
                //변수의 값이 null아닐때까지 반복 
                while (node != null)
                {
                    //비교 
                    var result = data.CompareTo(node.data);

                    if (result == 0)
                    {
                        //같으면 값이 이미 있음 
                        throw new ApplicationException("duplicated!");
                    }
                    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;

            //변수의 값이 null아닐경우 반복 
            while (node != null)
            {
                //검색하는 데이터와 변수에 있는 노드의 값과 비교 
                var result = data.CompareTo(node.data);

                //만약에 같다면 true 반환 
                if (result == 0)
                {
                    return true;
                }
                else if (result < 0)
                {
                    //작다면 변수에 왼쪽 노드 넣기 
                    node = node.left;
                }
                else
                {
                    //크다면 변수에 오른족 노드 넣기 
                    node = node.right;
                }
            }

            //못찾았다면 false 반환 
            return false;
        }
        //삭제 
        public bool Remove(int data)
        {

            //삭제할 노드 찾기 

            //node변수에 루트 넣기 
            var node = this.root;
            BSTNode prev = null;

            //node변수가 null이 아닐때까지 반복 
            while (node != null)
            {
                //삭제할 데이터와 node변수의 값을 비교 
                var result = data.CompareTo(node.data);
                //같다 (찾았다)
                if (result == 0)
                {
                    break;
                }
                else if (result < 0)
                {
                    //작다면 node변수에 node의 왼쪽 노드를 넣는다.
                    prev = node;
                    node = node.left;
                }
                else
                {
                    //크다면 node변수에 node의 오른쪽 노드를 넣는다 
                    prev = node;
                    node = node.right;
                }
            }

            if (node != null)
            {
                Console.WriteLine("삭제하려고 하는 노드를 찾았습니다. {0}노드 ", node.data);
            }
            else
            {
                Console.WriteLine("삭제하려고 하는 노드를 못찾았습니다.");
                return false;
            }

            //타겟 노드의 왼쪽과 오른쪽 노드가 없는경우 
            if (node.left == null && node.right == null)
            {
                //부모노드의 왼쪽과 찾으려고 하는 노드가 같다면 
                if (prev.left == node)
                {
                    prev.left = null;    //부모노드의 왼쪽노드를 없앰 
                }
                else
                {
                    prev.right = null;  //부모노드의 오른쪽노드를 없앰 
                }
            }
            else if (node.left == null || node.right == null)
            {
                //자식이 1개 인경우 

                //child 변수 선언 (찾은 노드의 자식)
                //node의 왼쪽 노드가 있다면 왼쪽노드를 없다면 오른쪽 노드를 할당 
                var child = node.left != null ? node.left : node.right;

                //부모의 왼쪽 노드와 node 비교 
                if (prev.left == node)
                {
                    //같다면 부모의 왼쪽 노드에 child 할당 
                    prev.left = child;
                }
                else
                {
                    //다르다면 부모노드의 오른쪽 노드에 child 할당 
                    prev.right = child;
                }
            }
            else
            {
                //자식 노드가 2개일경우 

                //pre 에 node넣기 
                var pre = node;
                //min 에 node의 오른쪽 노드 넣기 
                var min = node.right;

                //min에 왼쪽노드가 없을때까지 반복 
                while (min.left != null)
                {
                    //있으면 pre 에 min 넣기 
                    pre = min;
                    //min에 min왼쪽 노드 넣기 
                    min = min.left;
                }

                //node에 min의 값을 넣기 
                node.data = min.data;

                //pre의 왼쪽노드가 min과 같다면 제거 (null)
                if (pre.left == min)
                {
                    pre.left = min.right;
                }
                else
                {
                    //그렇지 않다면 pre의 오른쪽 노드를 제거 (null)
                    pre.right = min.right;
                }
            }


            return true;
        }
    }
}

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

namespace Study02
{
    public class App
    {
        //생성자 
        public App()
        {
            Console.WriteLine("App");
            BSTList bst = new BSTList();
            bst.Add(30);
            bst.Add(25);
            bst.Add(35);
            bst.Add(21);
            bst.Add(27);
            bst.Add(32);

            var list = bst.ToSortedList();
            bst.Print(list);

            var searchTarget = 25;
            var result = bst.Search(searchTarget);
            Console.WriteLine("searchTarget: {0}, result: {1}", searchTarget, result);

            var removeTarget = 25;
            result = bst.Remove(removeTarget);
            Console.WriteLine("removeTarget: {0}, result: {1}", searchTarget, result);

            list = bst.ToSortedList();
            bst.Print(list);
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Study02
{
    public class BSTList
    {
        private BSTNode root;

        public void Add(int data)
        {
            if (this.root == null)
            {
                this.root = new BSTNode(data);
            }
            else
            {
                //변수에 루트 담기 
                var node = this.root;
                //변수의 값이 null아닐때까지 반복 
                while (node != null)
                {
                    //비교 
                    var result = data.CompareTo(node.data);

                    if (result == 0)
                    {
                        //같으면 값이 이미 있음 
                        throw new ApplicationException("duplicated!");
                    }
                    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 List<BSTNode> ToSortedList() {
            //동적 배열 생성 
            List<BSTNode> list = new List<BSTNode>();
            this.Traversal(this.root, list);
            return list;
        }

        public bool Search(int data)
        {
            //변수에 루트 넣기 
            var node = this.root;

            //변수의 값이 null아닐경우 반복 
            while (node != null)
            {
                //검색하는 데이터와 변수에 있는 노드의 값과 비교 
                var result = data.CompareTo(node.data);

                //만약에 같다면 true 반환 
                if (result == 0)
                {
                    return true;
                }
                else if (result < 0)
                {
                    //작다면 변수에 왼쪽 노드 넣기 
                    node = node.left;
                }
                else
                {
                    //크다면 변수에 오른족 노드 넣기 
                    node = node.right;
                }
            }

            //못찾았다면 false 반환 
            return false;
        }
        //삭제 
        public bool Remove(int data)
        {

            //삭제할 노드 찾기 

            //node변수에 루트 넣기 
            var node = this.root;
            BSTNode prev = null;

            //node변수가 null이 아닐때까지 반복 
            while (node != null)
            {
                //삭제할 데이터와 node변수의 값을 비교 
                var result = data.CompareTo(node.data);
                //같다 (찾았다)
                if (result == 0)
                {
                    break;
                }
                else if (result < 0)
                {
                    //작다면 node변수에 node의 왼쪽 노드를 넣는다.
                    prev = node;
                    node = node.left;
                }
                else
                {
                    //크다면 node변수에 node의 오른쪽 노드를 넣는다 
                    prev = node;
                    node = node.right;
                }
            }

            if (node != null)
            {
                Console.WriteLine("삭제하려고 하는 노드를 찾았습니다. {0}노드 ", node.data);
            }
            else
            {
                Console.WriteLine("삭제하려고 하는 노드를 못찾았습니다.");
                return false;
            }

            //타겟 노드의 왼쪽과 오른쪽 노드가 없는경우 
            if (node.left == null && node.right == null)
            {
                //부모노드의 왼쪽과 찾으려고 하는 노드가 같다면 
                if (prev.left == node)
                {
                    prev.left = null;    //부모노드의 왼쪽노드를 없앰 
                }
                else
                {
                    prev.right = null;  //부모노드의 오른쪽노드를 없앰 
                }
            }
            else if (node.left == null || node.right == null)
            {
                //자식이 1개 인경우 

                //child 변수 선언 (찾은 노드의 자식)
                //node의 왼쪽 노드가 있다면 왼쪽노드를 없다면 오른쪽 노드를 할당 
                var child = node.left != null ? node.left : node.right;

                //부모의 왼쪽 노드와 node 비교 
                if (prev.left == node)
                {
                    //같다면 부모의 왼쪽 노드에 child 할당 
                    prev.left = child;
                }
                else
                {
                    //다르다면 부모노드의 오른쪽 노드에 child 할당 
                    prev.right = child;
                }
            }
            else
            {
                //자식 노드가 2개일경우 

                //pre 에 node넣기 
                var pre = node;
                //min 에 node의 오른쪽 노드 넣기 
                var min = node.right;

                //min에 왼쪽노드가 없을때까지 반복 
                while (min.left != null)
                {
                    //있으면 pre 에 min 넣기 
                    pre = min;
                    //min에 min왼쪽 노드 넣기 
                    min = min.left;
                }

                //node에 min의 값을 넣기 
                node.data = min.data;

                //pre의 왼쪽노드가 min과 같다면 제거 (null)
                if (pre.left == min)
                {
                    pre.left = min.right;
                }
                else
                {
                    //그렇지 않다면 pre의 오른쪽 노드를 제거 (null)
                    pre.right = min.right;
                }
            }


            return true;
        }


        private void Traversal(BSTNode node, List<BSTNode> list)
        {

            if (node == null) return;

            this.Traversal(node.left, list);
            list.Add(node); //중위순회 
            this.Traversal(node.right, list);
        }

        public void Print(List<BSTNode> list)
        {
            foreach (var node in list)
            {
                Console.Write("{0} ", node.data);
            }
            Console.WriteLine();
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Study02
{
    public class BSTNode
    {
        public int data;
        public BSTNode left;
        public BSTNode right;
        //생성자 
        public BSTNode(int data)
        {
            this.data = data;
        }
    }
}

 

Graph

 

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

namespace Study02
{
    public class App
    {
        //생성자 
        public App()
        {
            Graph graph = new Graph();

            //정점 생성
            var seoul = new Node("서울");
            graph.AddVertex(seoul);

            var daejun = new Node("대전");
            graph.AddVertex(daejun);
            var daeku = new Node("대구");
            graph.AddVertex(daeku);
            var busan = new Node("부산");
            graph.AddVertex(busan);
            var kangrung = new Node("강릉");
            graph.AddVertex(kangrung);

            //간선 연결
            graph.AddEdge(seoul, kangrung, 10);
            graph.AddEdge(seoul, daeku, 7);
            graph.AddEdge(seoul, daejun, 6);
            graph.AddEdge(daeku, busan, 3);
            graph.AddEdge(kangrung, daeku, 4);
            graph.AddEdge(daejun, busan, 7);
            graph.Print();
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Study02
{
    public class Graph
    {
        public List<Node> nodes;
        public bool directed;
        //생성자 
        public Graph(bool directed = false)
        {
            //컬렉션 초기화 
            this.nodes = new List<Node>();
        }

        //정점(Vertex) 추가 
        public void AddVertex(Node node)
        {
            this.nodes.Add(node);
        }

        //간선(Edge) 추가 
        public void AddEdge(Node from, Node to, int weight = 1)
        {
            from.Neighbors.Add(to);
            from.Weights.Add(weight);
            if (!this.directed)
            {
                to.Neighbors.Add(from);
                to.Weights.Add(weight);
            }
        }

        //출력 
        public void Print()
        {
            foreach (var vertex in this.nodes)
            {
                var cnt = vertex.Neighbors.Count;
                for (int i = 0; i < cnt; i++)
                {
                    Console.WriteLine("{0} -- ({1}) -- {2}",
                        vertex.Data, vertex.Weights[i], vertex.Neighbors[i].Data);
                }
            }
        }
    }
}

Dictionary Graph

 

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

namespace Study02
{
    public class App
    {
        //생성자 
        public App()
        {
            Graph graph = new Graph();
            graph.AddVertex("seoul");
            graph.AddVertex("busan");
            graph.AddVertex("mokpo");
            graph.AddVertex("gangrung");
            graph.AddVertex("daejun");
            graph.AddVertex("daeku");
            graph.AddEdge("seoul", "busan", 10);
            graph.AddEdge("seoul", "daejun", 5);
            graph.AddEdge("seoul", "daeku", 6);
            graph.AddEdge("seoul", "gangrung", 7);
            graph.AddEdge("seoul", "mokpo", 8);
            graph.AddEdge("daejun", "daeku", 3);
            graph.AddEdge("daejun", "busan", 5);
            graph.AddEdge("daejun", "mokpo", 4);

            graph.Print();


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

namespace Study02
{
    public class Graph
    {
        //컬렉션 
        private Dictionary<string, List<Node>> dic;

        //생성자 
        public Graph()
        {
            //인스턴스화 
            this.dic = new Dictionary<string, List<Node>>();
        }

        //vertex 추가 
        public void AddVertex(string key)
        {
            //키 중복 확인 
            if (!this.dic.ContainsKey(key))
            {
                this.dic.Add(key, new List<Node>());
            }
        }

        //Edge 연결 
        public void AddEdge(string from, string to, int weight)
        {
            //from에 인접리스트에 vertex추가 
            var list = this.dic[from];
            list.Add(new Node(to, weight));
        }

        //출력 
        public void Print()
        {
            foreach (var pair in this.dic)
            {
                var from = pair.Key;   //from  

                //from의 인접리스트들 
                //edge는 vertex
                foreach (var edge in pair.Value)
                {
                    Console.WriteLine("{0} -- ({1}) -- {2}", from, edge.weight, edge.key);
                }
            }
        }
    }
}

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

namespace Study02
{
    public class Node
    {
        public string key;  //키
        public int weight;  //가중치 
        //생성자 
        public Node(string key, int weight = 1)
        {
            this.key = key;
            this.weight = weight;
        }
    }
}

LinkedList Graph

 

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

namespace Study02
{
    public class App
    {
        //생성자 
        public App()
        {
            Graph graph = new Graph();
            graph.AddVertex("seoul");
            graph.AddVertex("busan");
            graph.AddVertex("mokpo");
            graph.AddVertex("gangrung");
            graph.AddVertex("daejun");
            graph.AddVertex("daeku");
            graph.AddEdge("seoul", "busan", 10);
            graph.AddEdge("seoul", "daejun", 5);
            graph.AddEdge("seoul", "daeku", 6);
            graph.AddEdge("seoul", "gangrung", 7);
            graph.AddEdge("seoul", "mokpo", 8);
            graph.AddEdge("daejun", "daeku", 3);
            graph.AddEdge("daejun", "busan", 5);
            graph.AddEdge("daejun", "mokpo", 4);

            graph.Print();


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

namespace Study02
{
    public class Edge
    {
        //시작
        public string from;
        //끝
        public string to;
        //가중치
        public int weight;

        public Edge(string from, string to, int weight)
        {
            this.from = from;
            this.to = to;
            this.weight = weight;
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Study02
{
    public class Graph
    {
        public List<Node> nodes;
        //생성자
        public Graph()
        {
            this.nodes = new List<Node>();
        }

        public void AddVertex(string key)
        {
            this.nodes.Add(new Node(key));
        }

        public void AddEdge(string from, string to, int weight)
        {
            //정점리스트에서 from키를 갖는 요소(Node)를 찾는다.
            var fromVertexs = this.nodes.Find(x => x.key == from);
            //찾은 정점에
            fromVertexs.edges.AddLast(new Edge(from, to, weight));
        }
       

        public void Print()
        {
            foreach(var vertex in this.nodes)
            {
                var from = vertex.key;

                foreach(var edge in vertex.edges)
                {
                    Console.WriteLine("[{0}]----[{1}]----[{2}]", edge.from, edge.weight, edge.to);
                }
            }
        }
        
    }
}

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

namespace Study02
{
    public class Node
    {
        public string key;  //키
        public LinkedList<Edge> edges;
        //생성자 
        public Node(string key)
        {
            this.key = key;
            this.edges = new LinkedList<Edge>();
        }
    }
}