티스토리 뷰
트리 구조의 탐색 앞서 이분 매칭에서 배운 대로 매우 유리하다. 반면에 순회 방법은 조금 복잡하다. 일정 조건에 의해 설계된 트리 구조는 자식 노드에 대한 조건이 명확하다면 내가 원하는 값을 쉽게 찾아낼 수 있다. 하지만, 트리구조 전체를 탐색하게 된다면 얘기가 조금 달라진다. 모든 노드를 방문하기 위해서는 트리 구조를 탐색하는 일정 조건이 필요하다. 트리 구조를 유지보수하는데 있어 순회 방법에 대한 정의는 필수적으로 필요하다. 이번 시간에는 트리 구조의 순회 방법에 대해 한번 알아보도록하자. 순회 방법을 쉽게 알 수 있게 이진 트리라는 조건으로 알아보지만, 다른 트리 구조에서도 충분히 적용할 수 있다.
1. 전위 순회 (Pre-order Traversal)
위의 트리를 살펴보면 12번 시작 노드에서 시작해서 좌측 자식 노드인 8번 노드로 이동하게 된다. 그 다음 8번 노드에서 다시 전위 순회 방식을 적용하게 되어 1번 노드로 이동하게 된다. 1번 노드의 경우 왼쪽 자신 노드가 없으므로 8번 노드에서 방문하려고 했던 우측 자식 노드인 11번을 순서대로 방문한다. 그 다음 다시 12번 노드에서 가야되었던 우측 자식 노드인 25번 노드로 이동한다. 이와 같은 순서대로 이동하게 된다면 아래와 같은 순서로 이동한다.
12 -> 8 -> 1 -> 11 -> 25 -> 19 -> 27
2. 중위 순회 (In-order Traversal)
1 -> 8 -> 11 -> 12 -> 19 -> 25 -> 27
3. 후위 순회 (Post-order Traversal)
후위 순회는 방문하려는 노드를 가장 마지막에 방문하는 방식이다. 좌측 자식 노드, 우측 자식 노드를 방문 한 다음 자신을 방문하는 구조다. 위의 트리에서 살펴보면 루트에서 시작해 좌측 서브트리로 이동한다. 8번 노드에 도달해서도 좌측으로 이동해 가장 먼저 방문하게 되는 노드는 1번 노드가 된다. 그 다음 우측 자식 노드인 11번으로 이동한다. 좌측, 우측을 모두 방문한 다음 상위 노드인 8번으로 이동하게 된다. 이제 다시 1번 노드 지점으로 돌아오게 되고 1번 노드의 우측 서브트리로 이동해 후위 순회를 진행한다.
1 -> 11 -> 8 -> 19 -> 27 -> 25 -> 12
트리 순회의 대표적인 3가지 방법이다. 트리 순회의 코드는 그리 어렵지 않으므로 직접 고민해보는 것도 좋은 방법이다. 아래 이진 트리 작성과 순회 방법에 대한 코딩을 첨부해 두었다.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132 import java.util.*; class Node{ // 데이터 선언 private int data; private Node left; private Node right; // Constructor public Node(int data){ this.setData(data); setRight(null); setLeft(null); } // getter, setter public int getData() {return data;} public void setData(int data) {this.data = data;} public Node getLeft() {return left;} public void setLeft(Node left) {this.left = left;} public Node getRight() {return right;} public void setRight(Node right) {this.right = right;}} public class Solution { public static Node root; public static void insert(int data){ Node node = new Node(data); if(root == null){ root = node; return; } Node current = root; Node temp = current; while(true){ if(current.getData()>data){ current = current.getLeft(); if(current == null){ temp.setLeft(node); return; } temp = current; } else if(current.getData()<data){ current = current.getRight(); if(current == null){ temp.setRight(node); return; } temp = current; } else{ System.out.println("중복된 값입니다."); return; } } } public static void preorder(Node node){ if (node == null){ return; } System.out.println(node.getData()); preorder(node.getLeft()); preorder(node.getRight()); } public static void inorder(Node node){ if (node == null){ return; } inorder(node.getLeft()); System.out.println(node.getData()); inorder(node.getRight()); } public static void postorder(Node node){ if (node == null){ return; } postorder(node.getLeft()); postorder(node.getRight()); System.out.println(node.getData()); } public static void main(String[] args) { // TODO Auto-generated method stub // 데이터 입력 insert(12); insert(8); insert(25); insert(1); insert(11); insert(19); insert(27); System.out.println("Preorder"); preorder(root); System.out.println("Inorder"); inorder(root); System.out.println("Postorder"); postorder(root); } } cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 | import java.util.*; class Node{ // 데이터 선언 private int data; private Node left; private Node right; // Constructor public Node(int data){ this.setData(data); setRight(null); setLeft(null); } // getter, setter public int getData() {return data;} public void setData(int data) {this.data = data;} public Node getLeft() {return left;} public void setLeft(Node left) {this.left = left;} public Node getRight() {return right;} public void setRight(Node right) {this.right = right;} } public class Solution { public static Node root; public static void insert(int data){ Node node = new Node(data); if(root == null){ root = node; return; } Node current = root; Node temp = current; while(true){ if(current.getData()>data){ current = current.getLeft(); if(current == null){ temp.setLeft(node); return; } temp = current; } else if(current.getData()<data){ current = current.getRight(); if(current == null){ temp.setRight(node); return; } temp = current; } else{ System.out.println("중복된 값입니다."); return; } } } public static void preorder(Node node){ if (node == null){ return; } System.out.println(node.getData()); preorder(node.getLeft()); preorder(node.getRight()); } public static void inorder(Node node){ if (node == null){ return; } inorder(node.getLeft()); System.out.println(node.getData()); inorder(node.getRight()); } public static void postorder(Node node){ if (node == null){ return; } postorder(node.getLeft()); postorder(node.getRight()); System.out.println(node.getData()); } public static void main(String[] args) { // TODO Auto-generated method stub // 데이터 입력 insert(12); insert(8); insert(25); insert(1); insert(11); insert(19); insert(27); System.out.println("Preorder"); preorder(root); System.out.println("Inorder"); inorder(root); System.out.println("Postorder"); postorder(root); } } | cs |
'Skill > Programming - Basic' 카테고리의 다른 글
23. 근사 알고리즘(Approximation Algorithm) (0) | 2019.02.05 |
---|---|
22. 허프만 부호화(Huffman Coding) (0) | 2019.01.25 |
20. 이진 탐색 트리(Binary Search Tree) (0) | 2018.12.30 |
19. 최대 이분 매칭(Maximun Bipartite Matching) (0) | 2018.12.25 |
18. 깊이 우선 탐색 (DFS algorithm) (1) | 2018.11.25 |