๐Ÿณ Laboon 2024. 7. 7. 23:02

ํŠธ๋ฆฌ ์ž๋ฃŒ๊ตฌ์กฐ์˜ ์ข…๋ฅ˜ : Tree, Binary Tree, Binary Serach Tree, Balanced Binary Serach Tree, Heap, Trie

์ด๋ฒˆ ํฌ์ŠคํŠธ์—์„œ๋Š” ๊ธฐ๋ณธ์ ์ธ Tree์— ๋Œ€ํ•ด์„œ๋งŒ ์ž‘์„ฑํ•ด๋ณด์ž.

 

Tree๋ž€ ?

 

Node์™€ Edge๋กœ ๊ตฌ์„ฑ๋œ ๋ฐฉํ–ฅ์ด ์กด์žฌํ•˜๋Š” ๋น„์ˆœํ™˜ Graph์˜ ํ•œ ์ข…๋ฅ˜์ด๋‹ค. ๊ทธ๋ž˜์„œ DAG(Directed Acyclic Graphs)๋ผ๊ณ ๋„ ํ•œ๋‹ค.

๊ทธ๋Ÿผ Graph๋กœ ๋ถ„๋ฅ˜ํ•˜๋ฉด ๋˜์ง€ ์™œ Tree๋ƒ๋Š” ์˜์‹ฌ์„ ํ•˜๊ฒŒ ๋œ๋‹ค.

Tree๋Š” Graph์—์„œ ๋ช‡๊ฐ€์ง€ ํŠน์„ฑ์„ ๋” ๊ฐ€์ง„๋‹ค.

 

1. ๋ฃจํŠธ ๋…ธ๋“œ๊ฐ€ ํ•˜๋‚˜ ์กด์žฌํ•œ๋‹ค.

2. ๋ถ€๋ชจ ๋…ธ๋“œ๋Š” ํ•˜๋‚˜๋ฐ–์— ์กด์žฌํ•˜์ง€ ์•Š๋Š”๋‹ค.

3. ๋…ธ๋“œ๋Š” 0๊ฐœ ์ด์ƒ์˜ ์ž์‹์„ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค.

4. ์ž์‹์ด 0๊ฐœ์ธ ๊ฒฝ์šฐ ๋‹จ๋ง๋…ธ๋“œ(Leaf Node)๋ผ๊ณ  ํ•œ๋‹ค.

5.. ์œ„ ํŠน์„ฑ์„ ์ง€ํ‚ค๋Š” ํŠธ๋ฆฌ์˜ ๊ฒฝ์šฐ ์—ฃ์ง€๊ฐ€ N-1๊ฐœ์ด๋‹ค.

6. ์—ฃ์ง€๊ฐ€ N-1๊ฐœ ์ด๋ฏ€๋กœ ๋‘ ์ •์ ๊ฐ„ ๊ฒฝ๋กœ๋Š” 1๊ฐ€์ง€์ด๋‹ค.

package com.study.datastructrue.nonlinear.tree;

import java.util.ArrayList;

public class Node<T> {
    private T data;
    private ArrayList<Node> children;

    public Node(final T data) {
       this.data = data;
       this.children = new ArrayList<>();
    }

    public T getData() {
       return data;
    }

    public void setData(final T data) {
       this.data = data;
    }

    public ArrayList<Node> getChildren() {
       return children;
    }

    public void add(Node data) {
       children.add(data);
    }

}

 

๊ธฐ๋ณธ์ ์ธ ๋…ธ๋“œ์˜ ์ •๋ณด์ด๋‹ค.

ํŠธ๋ฆฌ๋Š” DAG๋ผ๊ณ  ํ–ˆ์œผ๋ฏ€๋กœ ์ž์‹์ด ์—ฌ๋Ÿฌ๊ฐœ ์ผ ์ˆ˜ ์žˆ๋‹ค.

package com.study.datastructrue.nonlinear.tree;

import java.util.ArrayList;

public class MyTree<T> {

    private Node<T> root;

    public MyTree() {
       this.root = null;
    }

    public void add(T to, T data) {
       if (this.root == null) {
          this.root = new Node(data);
          return ;
       }
       final Node node = findFirst(to);
       if (node == null) {
          throw new IllegalArgumentException("NOT Found Node");
       }
       node.add(new Node(data));
    }

    public Node findFirst(T data) {
       if (root.getData() == data) return root;
       return findFirst(root, data);
    }

    private Node findFirst(Node<T> cur, T data) {
       for (int i = 0; i < cur.getChildren().size(); i++) {
          if (cur.getChildren().get(i).getData() == data) {
             return cur.getChildren().get(i);
          }
       }
       for (Node node : root.getChildren()) {
          return findFirst(node, data);
       }
       return null;
    }

    public void printTree() {
       ArrayList<StringBuilder> sbs = new ArrayList<>();
       final int depth = depth(root, 0);
       for (int i = 0; i <= depth; i++) {
          sbs.add(new StringBuilder());
       }
       printTree(root, 0, sbs);
       for (StringBuilder sb: sbs) {
          System.out.println(sb.toString());
       }
    }

    private int depth(Node<T> cur, int level) {
       int maxLevel = level;
       for (int i = 0; i < cur.getChildren().size(); i++) {
          maxLevel = Math.max(depth(cur.getChildren().get(i), level + 1), maxLevel);
       }
       return maxLevel;
    }

    private void printTree(Node<T> cur, int level, final ArrayList<StringBuilder> sbs) {
       StringBuilder sb = sbs.get(level);
       sb.append(cur.getData() + " ");
       for (int i = 0; i < cur.getChildren().size(); i++) {
          printTree(cur.getChildren().get(i), level + 1, sbs);
       }
       sb.append("|");

    }


}

 

์•„๋ฌด๋Ÿฐ ์ตœ์ ํ™” ์—†์ด ํŠธ๋ฆฌ๋ฅผ ์„ค๊ณ„ํ•˜๊ฒŒ ๋œ๋‹ค๋ฉด ์ด๋ ‡๊ฒŒ ํšจ์œจ์ ์ด์ง€ ๋ชปํ•˜๊ฒŒ ๋œ๋‹ค.

ํŠน์ • ๋…ธ๋“œ๋ฅผ ์ฐพ์„ ๋•Œ์—๋„ ์™„์ „ํƒ์ƒ‰์„ ํ•ด์•ผํ•˜๊ณ  ํŠน์ • ๋…ธ๋“œ์˜  ์ž์‹์œผ๋กœ ์ถ”๊ฐ€ํ•˜๋ ค๊ฑฐ๋‚˜ ๊ต์ฒดํ•˜๋ ค๋ฉด ํŠน์ • ๋…ธ๋“œ๋ฅผ ์ฐพ์•„์•ผํ•˜๋ฏ€๋กœ ๋˜ ๋‹ค์‹œ ์™„์ „ํƒ์ƒ‰์„ ํ•˜๊ฒŒ ๋œ๋‹ค.

 

์ด๋Ÿฐ ๋น„ํšจ์œจ์ ์ธ ๋ฌธ์ œ๋ฅผ ๊ฐœ์„ ํ•˜๊ธฐ ์œ„ํ•ด ์ด์ง„ ํƒ์ƒ‰ ํŠธ๋ฆฌ(Binary Search Tree)๋ผ๋Š” ๊ฒƒ์ด ๋‚˜์˜จ๋‹ค.

๊ธฐ์ค€ ๊ฐ’๋ณด๋‹ค ์ž‘์€ ๊ฐ’์€ ์™ผ์ชฝ์— ํฐ ๊ฐ’์€ ์˜ค๋ฅธ์ชฝ์— ๋น„์„ ํ˜•์ , ๊ณ„์ธต์ ์œผ๋กœ ์ €์žฅํ•ด์„œ Log_2 N๋ฒˆ๋งŒ์— ๊ฒ€์ƒ‰ํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค.

๊ทธ๋Ÿผ ์‚ผ์ง„, ์‚ฌ์ง„์œผ๋กœ ๋‚˜๋ˆ„๋ฉด ๋” ๋น ๋ฅด๊ฒŒ ๊ฒ€์ƒ‰ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ ์•„๋‹Œ๊ฐ€? ๋ผ๋Š” ์ƒ๊ฐ์ด ๋“ค์—ˆ๋Š”๋ฐ ์‹ค์ œ๋กœ DB์—์„œ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋‹ค. ์ด ๋ถ€๋ถ„์€ ๋‚˜์ค‘์— ์ž‘์„ฑ.

 

package com.study.datastructrue.nonlinear.tree;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;

public class Main {

    public static void main(String[] args) {
       // ๋ณต์žกํ•œ ํŠธ๋ฆฌ ์„ค๊ณ„
       MyTree<Integer> tree = new MyTree<>();

       tree.add(0, 1);
       tree.add(1, 2);
       tree.add(2, 3);
       tree.add(2, 4);
       tree.add(2, 5);

       tree.printTree();

       // PS์šฉ ๊ฐ„๋‹จํ•œ ADJ ํŠธ๋ฆฌ ์„ค๊ณ„
       int vertexCount = 10;
       int level[] = new int[vertexCount + 1];
       ArrayList<ArrayList<Integer>> tree2 = new ArrayList<>();
       ArrayList<StringBuilder> sbs = new ArrayList<>();
       for (int i = 0; i <= vertexCount; i++) {
          sbs.add(new StringBuilder());
          tree2.add(new ArrayList<>());
       }
       tree2.get(1).add(2);
       tree2.get(2).add(3);
       tree2.get(2).add(4);
       tree2.get(2).add(5);
       Queue<Integer> q = new LinkedList<>();
       q.add(1);  level[1] = 1;  sbs.get(1).append(1);
       int maxLevel = 1;
       // BFS
       while (!q.isEmpty()) {
          int x = q.poll();
          maxLevel = Math.max(maxLevel, level[x]);
          for (int i : tree2.get(x)) {
             level[i] = level[x] + 1;
             sbs.get(level[i]).append(i + " ");
             q.add(i);
          }
       }
       for (int i = 1; i <= maxLevel; i++) {
          System.out.println(sbs.get(i).toString());
       }
    }

}

 

Graph์— ๊ฐ€๊นŒ์šด Tree ์‚ฌ์šฉ๊ณผ PS ์šฉ์œผ๋กœ ์งง๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์ฝ”๋“œ