diff --git a/09/beom/BinTree.java b/09/beom/BinTree.java new file mode 100644 index 00000000..90878bec --- /dev/null +++ b/09/beom/BinTree.java @@ -0,0 +1,209 @@ +package algorithmStudyTree; + +import java.util.Comparator; +import java.util.LinkedList; +import java.util.Queue; + +public class BinTree { + static class Node{ + private K key; + private V data; + private Node left; + private Node right; + + public Node(K key, V data, Node left, Node right) { + this.key = key; + this.data = data; + this.left = left; + this.right = right; + } + + public K getKey() { + return key; + } + + public V getData() { + return data; + } + + void print(){ + System.out.println(data); + } + } + + private Node root; + private Comparator comparator =null; //비교자 + + public BinTree() { + root = null; + } + + public BinTree(Comparator c) { + this(); + this.comparator = c; + } + + private int comp(K key1, K key2){ + return (comparator == null) ? ((Comparable) key1).compareTo(key2) + : comparator.compare(key1, key2); + } + + public V search(K key){ + Node p = root; + + while(true){ + if(p==null) + return null; + int cond = comp(key, p.getKey()); + if(cond == 0){ + //System.out.println(p.getData()); + return p.getData(); + } + else if(cond <0) + p = p.left; + else + p=p.right; + } + } + + private void addNode(Node node, K key, V data){ + int cond = comp(key, node.getKey()); + if(cond ==0) + return; + else if(cond < 0){ + if(node.left == null) + node.left = new Node(key, data,null,null); + else + addNode(node.left, key,data); + } else{ + if(node.right == null) + node.right = new Node(key, data,null,null); + else + addNode(node.right, key,data); + } + } + + //addNode는 private로 외부에서 사용x + public void add(K key, V data){ + if(root == null) + root = new Node(key,data,null,null); + else + addNode(root, key, data); + } + + public boolean remove(K key){ + Node p = root; + Node parent = null; + boolean isLeftChild = true; + + while (true){ + if(p==null) + return false; + int cond = comp(key,p.getKey()); + if (cond == 0) + break; + else{ + parent = p; + if(cond < 0){ + isLeftChild = true; + p = p.left; + } else { + isLeftChild = false; + p = p.right; + } + } + } + + if(p.left == null){ + if(p == root) + root = p.right; + else if(isLeftChild) + parent.left = p.right; + else + parent.right = p.right; + } else if(p.right ==null){ + if(p == root) + root = p.left; + else if(isLeftChild) + parent.left = p.left; + else + parent.right = p.left; + } else{ + parent = p; + Node left = p.left; + isLeftChild = true; + while(left.right != null){ + parent = left; + left = left.right; + isLeftChild = false; + } + p.key = left.key; + p.data = left.data; + if(isLeftChild) + parent.left = left.left; + else + parent.right = left.left; + } + return true; + } + + private void preOrder(Node node){ + if(node != null){ + System.out.print(node.data + " " ); + if(node.left != null) preOrder(node.left); + if(node.right != null) preOrder(node.right); + } + } + + public void printPreOrder(){ + preOrder(root); + } + + private void inOrder(Node node){ + if(node != null){ + if(node.left != null) inOrder(node.left); + System.out.print(node.data + " "); + if(node.right != null) inOrder(node.right); + } + } + + public void printInOrder(){ + inOrder(root); + } + + private void postOrder(Node node){ + if(node != null){ + if(node.left != null) postOrder(node.left); + if(node.right != null) postOrder(node.right); + System.out.print(node.data + " "); + } + } + + public void printPostOrder(){ + postOrder(root); + } + + private void levelOrder(Node a){ + Queue queue= new LinkedList<>(); + queue.offer(a); + + while(!queue.isEmpty()){ + Node node = queue.poll(); + System.out.print(node.getData()+ " "); + + if(node.left != null){ + queue.offer(node.left); + } + + if(node.right != null){ + queue.offer(node.right); + } + } + } + + public void printLevelOrder(){ + levelOrder(root); + } + + +} diff --git a/09/beom/Leetcode.md b/09/beom/Leetcode.md new file mode 100644 index 00000000..ffa1980d --- /dev/null +++ b/09/beom/Leetcode.md @@ -0,0 +1,182 @@ +# Tree +## 목차 +- 99. Recover Binary Search Tree +- 222. Count Complete Tree Nodes +- 112. Path Sum + + +## 99. Recover Binary Search Tree +### 문제 요약 +BST의 순서가 잘못된 것을 복원하시오 + +> 풀이
+> 주어진 root를 중위순회 방식으로 하여 오름차순 또는 내림차순으로 정렬된 배열을 바꿔야할 것같다는 생각까지만 들었다. 하지만 그 이후로는 생각이 나지 않아 discuss의 도움을 받았다. + +### 시간 복잡도 공간복잡도 +| time | space | +|------|-------| +| O(n) | O(n) | + +### 코드 +```java +class Solution { + TreeNode prev = null; + TreeNode first = null; + TreeNode second = null; + + public void recoverTree(TreeNode root) { + inOrder(root); + int temp = first.val; + first.val = second.val; + second.val = temp; + } + + public void inOrder(TreeNode root){ + if(root==null)return; + inOrder(root.left); + + if(prev!=null&&root.val 트리의 차수가 2 이하인 트리 + +- 비선형 자료구조 +- 자식이 최대 2개이기 때문에 자식을 왼쪽 자식과 오른쪽 자식으로 구분 +- 높이가 `N`인 이진 트리의 최대 노드 갯수는 2^N -1 개이다. + +### 정 이진 트리(Full Binary Tree) +> 모든 노드의 차수가 0 또는 2인 이진 트리 + +### 포화 이진 트리(Perfect Binary Tree) +> 정 이진 트리에서 단말 노드 제외 모든 노드가 두 개의 자식 노드를 가지고 모든 노드의 동일한 깊이 또는 레벨을 가지는 트리 + +![포화 이진 트리](asset/perfect_binary_tree.png) + +### 완전 이진 트리(Complete Binary Tree) +> 마지막 레벨을 제외하고 모든 레벨이 완전히 채워져 있고 마지막 레벨의 모든 노드는 가능한 가장 왼쪽에 있는 트리 + +![완전 이진 트리](asset/complete_binary_tree.png) + + +## 트리의 순회 + +1. 전위 순회(Pre-order) : 현재 노드 방문 -> 왼쪽 자식 탐색 -> 오른쪽 자식 탐색 +2. 중위 순회(In-order) : 왼쪽 자식 탐색 -> 현재 노드 방문 -> 오른쪽 자식 탐색 +3. 후위 순회(Post-order) : 왼쪽 자식 탐색 -> 오른쪽 자식 탐색 -> 현재노드 방문 + +## Java에서의 Tree + +자바의 Collection Framework는 `treeset`과 `treemap`을 지원한다. + +`treeset`과 `treemap`은 내부적으로 어떤 자료구조를 사용하고 있을까? + +바로 `레드블랙트리(Red-Black-Tree)`를 사용한다. + +레드블랙트리의 자세한 내용은 아래 링크를 참고하자 + +[레드블랙트리링크](https://devlog-wjdrbs96.tistory.com/159?category=882242) + +간단하게 설명하자면 데이터가 한쪽으로 편향되는 경우를 방지하기 위해 삽입시에 레드 블랙트리의 조건에 의해 균형이 맞춰진 트리가 만들어진다. + +중요한 것은 BST의 연산의 시간복잡도는 트리의 높이만큼 증가하는데 편향된 트리(O(n))에서 균형이 잡힌 트리(O(logn))으로 줄였다는 것이다. + +`treeset`과 `treemap`의 **차이점**은 + +`treeset`은 그냥 값만 저장한다면 `treemap`은 키와 값이 저장된 Map, Entry를 저장한다는 것이다. + +## 트리의 시간복잡도\ +- treeset, treemap 동일 +- 노드 삽입 : O(log n) +- 노드 삭제 : O(log n) +- 노드 검색 : O(log n) diff --git a/09/beom/Tree.pptx b/09/beom/Tree.pptx new file mode 100644 index 00000000..d5c4fddb Binary files /dev/null and b/09/beom/Tree.pptx differ diff --git a/09/beom/TreeTest.java b/09/beom/TreeTest.java new file mode 100644 index 00000000..4ed515a4 --- /dev/null +++ b/09/beom/TreeTest.java @@ -0,0 +1,26 @@ +package algorithmStudyTree; + +public class implementTree { + + public static void main(String[] args) { + BinTree binTree = new BinTree<>(); + + binTree.add(30,30); + binTree.add(25,25); + binTree.add(90,90); + binTree.add(19,19); + binTree.add(26,26); + binTree.add(77,77); + binTree.add(99,99); + binTree.add(5,5); + + binTree.printPreOrder(); + System.out.println(); + binTree.printInOrder(); + System.out.println(); + binTree.printPostOrder(); + System.out.println(); + binTree.printLevelOrder(); + System.out.println(); + } +} \ No newline at end of file diff --git a/09/beom/asset/complete_binary_tree.png b/09/beom/asset/complete_binary_tree.png new file mode 100644 index 00000000..e75a945d Binary files /dev/null and b/09/beom/asset/complete_binary_tree.png differ diff --git a/09/beom/asset/perfect_binary_tree.png b/09/beom/asset/perfect_binary_tree.png new file mode 100644 index 00000000..9d643a7d Binary files /dev/null and b/09/beom/asset/perfect_binary_tree.png differ diff --git a/09/beom/asset/tree.png b/09/beom/asset/tree.png new file mode 100644 index 00000000..8a0afd99 Binary files /dev/null and b/09/beom/asset/tree.png differ diff --git a/ADT/beom/Tree/binTree.java b/ADT/beom/Tree/binTree.java new file mode 100644 index 00000000..efb8ad28 --- /dev/null +++ b/ADT/beom/Tree/binTree.java @@ -0,0 +1,214 @@ +```java +package algorithmStudyTree; + +import java.security.PublicKey; +import java.util.Comparator; +import java.util.LinkedList; +import java.util.Queue; + +public class BinTree { + static class Node{ + private K key; + private V data; + private Node left; + private Node right; + + public Node(K key, V data, Node left, Node right) { + this.key = key; + this.data = data; + this.left = left; + this.right = right; + } + + public K getKey() { + return key; + } + + public V getData() { + return data; + } + + void print(){ + System.out.println(data); + } + } + + private Node root; + private Comparator comparator =null; //비교자 + + public BinTree() { + root = null; + } + + public BinTree(Comparator c) { + this(); + this.comparator = c; + } + + private int comp(K key1, K key2){ + return (comparator == null) ? ((Comparable) key1).compareTo(key2) + : comparator.compare(key1, key2); + } + + public V search(K key){ + Node p = root; + + while(true){ + if(p==null) + return null; + int cond = comp(key, p.getKey()); + if(cond == 0){ + //System.out.println(p.getData()); + return p.getData(); + } + else if(cond <0) + p = p.left; + else + p=p.right; + } + } + + private void addNode(Node node, K key, V data){ + int cond = comp(key, node.getKey()); + if(cond ==0) + return; + else if(cond < 0){ + if(node.left == null) + node.left = new Node(key, data,null,null); + else + addNode(node.left, key,data); + } else{ + if(node.right == null) + node.right = new Node(key, data,null,null); + else + addNode(node.right, key,data); + } + } + + //addNode는 private로 외부에서 사용x + public void add(K key, V data){ + if(root == null) + root = new Node(key,data,null,null); + else + addNode(root, key, data); + } + + public boolean remove(K key){ + Node p = root; + Node parent = null; + boolean isLeftChild = true; + + while (true){ + if(p==null) + return false; + int cond = comp(key,p.getKey()); + if (cond == 0) + break; + else{ + parent = p; + if(cond < 0){ + isLeftChild = true; + p = p.left; + } else { + isLeftChild = false; + p = p.right; + } + } + } + + if(p.left == null){ + if(p == root) + root = p.right; + else if(isLeftChild) + parent.left = p.right; + else + parent.right = p.right; + } else if(p.right ==null){ + if(p == root) + root = p.left; + else if(isLeftChild) + parent.left = p.left; + else + parent.right = p.left; + } else{ + parent = p; + Node left = p.left; + isLeftChild = true; + while(left.right != null){ + parent = left; + left = left.right; + isLeftChild = false; + } + p.key = left.key; + p.data = left.data; + if(isLeftChild) + parent.left = left.left; + else + parent.right = left.left; + } + return true; + } + + private void preOrder(Node node){ + if(node != null){ + System.out.print(node.data + " " ); + if(node.left != null) preOrder(node.left); + if(node.right != null) preOrder(node.right); + } + } + + public void printPreOrder(){ + preOrder(root); + } + + private void inOrder(Node node){ + if(node != null){ + if(node.left != null) inOrder(node.left); + System.out.print(node.data + " "); + if(node.right != null) inOrder(node.right); + } + } + + public void printInOrder(){ + inOrder(root); + } + + private void postOrder(Node node){ + if(node != null){ + if(node.left != null) postOrder(node.left); + if(node.right != null) postOrder(node.right); + System.out.print(node.data + " "); + } + } + + public void printPostOrder(){ + postOrder(root); + } + + private void levelOrder(Node a){ + Queue queue= new LinkedList<>(); + queue.offer(a); + + while(!queue.isEmpty()){ + Node node = queue.poll(); + System.out.print(node.getData()+ " "); + + if(node.left != null){ + queue.offer(node.left); + } + + if(node.right != null){ + queue.offer(node.right); + } + } + } + + public void printLevelOrder(){ + levelOrder(root); + } + + +} + + +```