diff --git a/changhee/src/main/java/com/dataStructure/Main.java b/changhee/src/main/java/com/dataStructure/Main.java index 4e268e0..96be74e 100644 --- a/changhee/src/main/java/com/dataStructure/Main.java +++ b/changhee/src/main/java/com/dataStructure/Main.java @@ -1,60 +1,34 @@ package com.dataStructure; -import com.dataStructure.collections.arrayDeque.MyArrayDeque; -import com.dataStructure.collections.arrayList.ArrayList; -import com.dataStructure.collections.arrayList.MyList; -import com.dataStructure.collections.arrayStack.MyArrayStack; -import com.dataStructure.collections.circularSinglyLinkedList.CircularSinglyLinkedList; -import com.dataStructure.collections.linkedList.MyDoublyLinkedList; -import com.dataStructure.collections.linkedList.MySingleLinkedList; -import com.dataStructure.collections.linkedQueue.MyLinkedQueue; -import com.dataStructure.collections.linkedStack.MyLinkedStack; + +import com.dataStructure.collections.binaryTree.MyBinaryTree; public class Main { public static void main(String[] args) { - MyLinkedStack list = new MyLinkedStack<>(); - System.out.println("빈 리스트가 출력되어야 한다"); - System.out.println("list = " + list); - System.out.println(); - - System.out.println("list는 1, 2, 3, 4를 포함해야 한다"); - list.push(1L); - list.push(2L); - list.push(3L); - list.push(4L); - System.out.println("list = " + list); - System.out.println(); - - System.out.println("값 4가 삭제되어야 한다"); - System.out.println("삭제 된 값 : "+list.pop()); - System.out.println("list = " + list); - System.out.println(); - - System.out.println("list의 크기는 3이어야 한다"); - System.out.println("list.size() = " + list.size()); - System.out.println(); - - System.out.println("list 마지막 값인 3이 나와야한다."); - System.out.println("list.peek() = " + list.peek()); - System.out.println(); - - System.out.println("list 첫 번째 값인 1이 나와야한다."); - System.out.println("list.search = " + list.search(1L)); - System.out.println("list = " + list); - System.out.println(); - - System.out.println("list에 4가 없으므로 -1이 나와야 한다."); - System.out.println("list.search = " + list.search(4)); - System.out.println(); - - - System.out.println("clear를 하면 list는 비어있어야 한다"); - list.clear(); - System.out.println("list = " + list); - System.out.println(); - - System.out.println("clear를 하면 list는 비어있어야 한다"); - System.out.println("list.empty() =" + list.isEmpty()); + MyBinaryTree tree = new MyBinaryTree<>(); + // 예제에 있는 트리와 동일하게 구성 + tree.add(23); + tree.add(12); + tree.add(40); + tree.add(7); + tree.add(16); + tree.add(1); + tree.add(14); + tree.add(17); + tree.add(29); + tree.add(55); + tree.add(61); + + System.out.print("전위 순회 : "); + tree.preorder(); // 전위 순회 + System.out.println(); + + System.out.print("중위 순회 : "); + tree.inorder(); // 중위 순회 + System.out.println(); + + System.out.print("후위 순회 : "); + tree.postorder(); // 후위 순회 System.out.println(); } } \ No newline at end of file diff --git a/changhee/src/main/java/com/dataStructure/collections/binarySearchTree/CustomBinarySearchTree.java b/changhee/src/main/java/com/dataStructure/collections/binarySearchTree/CustomBinarySearchTree.java new file mode 100644 index 0000000..2de92d1 --- /dev/null +++ b/changhee/src/main/java/com/dataStructure/collections/binarySearchTree/CustomBinarySearchTree.java @@ -0,0 +1,21 @@ +package com.dataStructure.collections.binarySearchTree; + +public interface CustomBinarySearchTree { + boolean add(E value); + + E remove(Object o) ; + + int size() ; + + boolean isEmpty(); + + boolean contains(Object o); + + void clear(); + + void preorder(); + + void inorder(); + + void postorder(); +} diff --git a/changhee/src/main/java/com/dataStructure/collections/binarySearchTree/MyBinarySearchTree.java b/changhee/src/main/java/com/dataStructure/collections/binarySearchTree/MyBinarySearchTree.java new file mode 100644 index 0000000..fa1ad52 --- /dev/null +++ b/changhee/src/main/java/com/dataStructure/collections/binarySearchTree/MyBinarySearchTree.java @@ -0,0 +1,78 @@ +package com.dataStructure.collections.binarySearchTree; + + +public class MyBinarySearchTree implements CustomBinarySearchTree{ + + private Node root; + private int size; + public MyBinarySearchTree(){ + this.root = null; + size = 0; + } + + + public class Node{ + private Object value; + private Node leftChild; + private Node rightChild; + + public Node(Object value){ + this.value = value; + this.leftChild = null; + this.rightChild = null; + } + } + + @Override + public boolean add(Object value) { + + if(root == null){ + Node newNode = new Node(value); + root = newNode; + size++; + } + Node current = root; + return false; + } + + @Override + public Object remove(Object o) { + return null; + } + + @Override + public int size() { + return 0; + } + + @Override + public boolean isEmpty() { + return false; + } + + @Override + public boolean contains(Object o) { + return false; + } + + @Override + public void clear() { + + } + + @Override + public void preorder() { + + } + + @Override + public void inorder() { + + } + + @Override + public void postorder() { + + } + +} diff --git a/changhee/src/main/java/com/dataStructure/collections/binaryTree/CustomBinaryTree.java b/changhee/src/main/java/com/dataStructure/collections/binaryTree/CustomBinaryTree.java new file mode 100644 index 0000000..fd922cd --- /dev/null +++ b/changhee/src/main/java/com/dataStructure/collections/binaryTree/CustomBinaryTree.java @@ -0,0 +1,28 @@ +package com.dataStructure.collections.binaryTree; + + +public interface CustomBinaryTree> { + + Node getRoot(); + + void setRoot(Node root); + + // 데이터 제일 마지막에 삽입 + boolean add(T data); + + // 해당 data와 일치하는 데이터 지우기 맨 마지막 값 삭제하기 + boolean remove(T data); + + // 검색 메서드 + boolean search(T data); + + // 중위 순회 출력하기 + void inorderTraversal(); + + // 전위 순회 메서드 + void preorderTraversal(); + + // 후위 순회 메서드 + void postorderTraversal(); + +} diff --git a/changhee/src/main/java/com/dataStructure/collections/binaryTree/MyBinaryTree.java b/changhee/src/main/java/com/dataStructure/collections/binaryTree/MyBinaryTree.java new file mode 100644 index 0000000..c8cd0cb --- /dev/null +++ b/changhee/src/main/java/com/dataStructure/collections/binaryTree/MyBinaryTree.java @@ -0,0 +1,435 @@ +package com.dataStructure.collections.binaryTree; + +import java.util.Comparator; + +public class MyBinaryTree { + + private Node root; + private int size; + + private final Comparator comparator; + + public MyBinaryTree(){ + this(null); + } + + public MyBinaryTree(Comparator comparator){ + this.comparator = comparator; + this.root = null; + this.size = 0; + } + + public boolean add(E value){ + if(comparator == null){ + return addUsingComparable(value) == null; + } + return addUsingComparator(value, comparator) == null; + } + + private E addUsingComparable(E value) { + Node current = root; + + if(current == null){ + root = new Node(value); + size++; + return null; + } + + Node currentParent; + + Comparable compValue = (Comparable) value; + + int compResult; + + do{ + currentParent = current; + + compResult = compValue.compareTo(current.value); + + if(compResult < 0){ + current = current.left; + }else if(compResult > 0){ + current = current.right; + }else{ + return value; + } + + }while(current != null); + + Node newNode = new Node(value, currentParent); + + if(compResult < 0){ + currentParent.left = newNode; + }else{ + currentParent.right = newNode; + } + size++; + return null; + } + + private E addUsingComparator(E value, Comparator comparator) { + + Node current = root; + + if(current == null){ + root = new Node(value, null); + size++; + return null; + } + + Node currentParent; + int compResult; + do{ + currentParent = current; + compResult = comparator.compare(value, current.value); + + if(compResult < 0){ + current = current.left; + }else if(compResult > 0){ + current = current.right; + }else{ + return value; + } + }while(current != null); + + Node newNode = new Node(value, currentParent); + if(compResult < 0){ + currentParent.left = newNode; + }else { + currentParent.right = newNode; + } + size++; + return null; + } + + // 삭제 메소드 + + /** + * 삭제되는 노드의 자리를 대체할 노드(후계자)를 찾는 메소드 + * (오른쪽 자식 노드 중 가장 작은 노드를 찾음) + * + * @param node 삭제되는 노드(=대체되어야 할 노드) + * @return 대체할 노드 + * */ + private Node getSuccessorAndUnlink(Node node){ + + Node currentParent = node; // 대체 할 노드의 부모노드를 가리키는 노드 + Node current = node.right; // 초기에 오른쪽 자식 노드를 가리키도록 한다. + + /** + * 처음 탐색하게되는 오른쪽 자식 노드(current)에서 + * current의 왼쪽 자식이 없다는 것은 current 노드, + * 즉 오른쪽 첫 자식노드가 대체되는 노드가 된다는 것이다. + * + * 그렇기 때문에 대체해야하는 노드는 삭제되는 노드의 오른쪽 자식이 되며 + * 이에 대체되는 노드 자리(currentParent)의 오른쪽 자식은 + * current의 오른쪽 자식을 가리키고, currentParent는 이후 + * current의 값이 반환되고, 상위 메소드에서 currentParent자리에 + * 값이 대체되게 된다. + * */ + if(currentParent.left == null){ + currentParent.right = current.right; + if(currentParent.right != null){ + currentParent.right.parent = currentParent; + } + current.right = null; + return current; + } + + // 가장 작은 노드를 찾을 때까지 반복한다. + while(current.left != null){ + currentParent = current; + current = current.left; + } + + /** + * 만약 후계자가 될 노드(가장 작은 노드)의 오른쪽 노드가 존재한다면 + * currentParent의 왼쪽 자식노드는 오른쪽 자식노드와 연결되어야 한다. + * + * 만약 current.right = null 이라면 + * 후계자가 될 노드의 자식노드는 존재하지 않으므로 자연스럽게 + * 후계자 노드의 부모노드는 후계자가 다른노드로 대체되러 가기 때문에 + * 후계자의 부모노드의 왼쪽자식노드는 자연스럽게 null을 가르키게 된다. + * */ + currentParent.left = current.right; + if(currentParent.left != null){ + currentParent.left.parent = currentParent; + } + + current.right = null; + return current; + } + + /** + * 삭제 할 노드에 대해 삭제를 수행하는 메소드 + * + * @param node 삭제 할 노드 + * @return 삭제 후 대체 되고 난 뒤의 해당 위치의 노드를 반환 + * */ + private Node deleteNode(Node node){ + if(node != null){ + // 자식노드가 없을 경우 + if(node.left == null && node.right == null){ + // 삭제하려는 노드가 root일 경우 root를 끊어버리고 종료한다. + if(node == root){ + root = null; + } + // 그 외에는 단말 노드이므로 해당 노드만 삭제한다. + // 자연스럽게 node의 부모노드는 null을 참조하게 됨 + else{ + node = null; + } + return null; + } + + // 양쪽의 자식노드가 모두 있을 경우 + if(node.left != null && node.right != null){ + // 대체 노드를 찾아온다. (앞선 만들었던 후계자를 찾는 메소드다) + Node replacement = getSuccessorAndUnlink(node); + // 삭제 된 노드에 대체 노드의 값을 대체해준다. + node.value = replacement.value; + } + // 왼쪽 노드만 존재할 경우 + else if(node.left != null){ + /** + * 삭제할 노드가 root일 경우 왼쪽자식 노드(대체되는 노드)를 + * 삭제할 노드로 옮긴 다음 root를 대체노드를 가리키도록 변경한다. + * */ + if(node == root){ + node = node.left; + root = node; + root.parent = null; + }else{ + node = node.left; + } + } + // 오른쪽 노드만 존재할 경우 + else{ + /** + * 삭제할 노드가 root일 경우 오른쪽 자식 노드(대체되는 노드)를 + * 삭제할 노드로 옮긴 다음 root를 대체노드를 가리키도록 변경한다. + * */ + if(node == root){ + node = node.right; + root = node; + root.parent = null; + }else { + node = node.right; + } + } + } + return node; + } + + /** + * 삭제 메소드 + * @param o 삭제할 값 + * @return 삭제 된 노드의 value 값 혹은 매칭 값이 없을 경우 null을 반환한다. + * */ + public E remove(Object o){ + if(root == null){ + return null; + } + if(comparator == null){ + return removeUsingComparable(o); + }else{ + return removeUsingComparator(o, comparator); + } + } + + private E removeUsingComparable(Object value){ + E oldVal = (E) value; + Node parent = null; + Node current = root; + + boolean hasLeft = false; + + if(root == null){ + return null; + } + + Comparable compValue = (Comparable) value; + + do{ + int resComp = compValue.compareTo(current.value); + if(resComp == 0){ + break; + } + + parent = current; + if(resComp < 0){ + hasLeft = true; + current = current.left; + }else{ + hasLeft = false; + current = current.right; + } + }while(current != null); + + if(current == null){ + return null; + } + + if(parent == null){ + deleteNode(current); + size--; + return oldVal; + } + + if(hasLeft){ + parent.left = deleteNode(current); + if(parent.left != null){ + parent.left.parent = parent; + } + }else{ + parent.right = deleteNode(current); + if(parent.right != null){ + parent.right.parent = parent; + } + } + size--; + return oldVal; + } + + private E removeUsingComparator(Object value, Comparator comp){ + E oldVal = (E) value; + Node parent = null; + Node current = root; + boolean hasLeft = false; + + if(root == null){ + return null; + } + + E compValue = (E) value; + + do{ + int resComp = comp.compare(compValue, current.value); + if(resComp == 0){ + break; + } + + parent = current; + if(resComp < 0){ + hasLeft = true; + current = current.left; + }else{ + hasLeft = false; + current = current.right; + } + }while(current != null); + + if(current == null){ + return null; + } + + if(parent == null){ + deleteNode(current); + size--; + return oldVal; + } + + if(hasLeft){ + parent.left = deleteNode(current); + if(parent.left != null){ + parent.left.parent = parent; + } + }else{ + parent.right = deleteNode(current); + if(parent.right != null){ + parent.right.parent = parent; + } + } + size--; + return oldVal; + } + + public int size(){ + return this.size; + } + + public boolean isEmpty(){ + return size() == 0; + } + + public boolean contains(Object o){ + if(comparator == null){ + return containsUsingComparable(o); + } + return containsUsingComparator(o, comparator); + } + + private boolean containsUsingComparable(Object o){ + Comparable value = (Comparable) o; + + Node node = root; + while(node != null){ + int res = value.compareTo(node.value); + if(res == 0){ + return true; + }else if(res < 0){ + node = node.left; + }else{ + node = node.right; + } + } + return false; + } + + private boolean containsUsingComparator(Object o, Comparator comparator){ + E value = (E) o; + Node node = root; + while(node != null){ + int res = comparator.compare(value, node.value); + if(res < 0){ + node = node.left; + }else if(res > 0){ + node = node.right; + }else{ + return true; + } + } + return false; + } + + public void clear(){ + size = 0; + root = null; + } + + public void preorder(){ + preorder(this.root); + } + + public void preorder(Node o){ + if(o != null){ + System.out.print(o.value + " "); + preorder(o.left); + preorder(o.right); + } + } + + public void inorder(){ + inorder(this.root); + } + + public void inorder(Node o){ + if(o != null){ + inorder(o.left); + System.out.print(o.value + " "); + inorder(o.right); + } + } + + public void postorder(){ + postorder(this.root); + } + + public void postorder(Node o){ + if(o != null){ + postorder(o.left); + postorder(o.right); + System.out.print(o.value + " "); + } + } +} diff --git a/changhee/src/main/java/com/dataStructure/collections/binaryTree/Node.java b/changhee/src/main/java/com/dataStructure/collections/binaryTree/Node.java new file mode 100644 index 0000000..51d879a --- /dev/null +++ b/changhee/src/main/java/com/dataStructure/collections/binaryTree/Node.java @@ -0,0 +1,21 @@ +package com.dataStructure.collections.binaryTree; + +public class Node{ + E value; + Node left; + Node right; + Node parent; + + Node(E value){ + this(value, null); + } + + Node(E value, Node parent){ + this.value = value; + this.parent = parent; + left = null; + right = null; + } + + +}