[자료 구조 기초] Tree
Tree
Tree : 그래프의 구조 중 하나로 단방향 계층적 구조이며, 하나의 뿌리로부터 가지가 사방으로 뻗은 형태이다.
Tree 구조 및 특징

- Node : 트리 구조를 이루는 모든 개별 데이터
 - Root : 트리 구조의 시작점이 되는 노드
 - Parent Node : 두 노드가 상하관계로 연결되어 있을 때 상대적을으로 루트에서 가까운 노드
 - Child Node : 두 노드가 상하관계로 연결되어 있을 때 상대적으로 루트에서 먼 노드
 - Leaf Node : 트리 구조의 끝 지점이고, 자식 노드가 없는 노드
 

- Depth : 루트로부터 하위 계층의 특정 노드까지의 깊이
 - Level : 같은 깊이를 가지고 있는 노드을 묶어서 레벨이라고 표현, 같은 레벨에 있는 노드를 형제 노드(Sibling Node)라고 한다.
 - Height : 리프 노드를 기준으로 루트까지의 높이
 - Sub Tree : 트리 구조를 갖춘 작은 트리
 
예제
class Tree {
    constructor(value) {
          // constructor로 만든 객체는 트리의 Node가 됩니다.
      this.value = value;
      this.children = [];
    }
  
      // 트리의 삽입 메서드를 만듭니다.
    insertNode(value) {
      const childNode = new Tree(value);
      this.children.push(childNode);
    }
  
      // 트리 안에 해당 값이 포함되어 있는지 확인하는 메서드를 만듭니다.
    contains(value) {
      if (this.value === value ) {
        return true;
      }
      
      for(let i=0;i<this.children.length;i++) {
        if(this.children[i].contains(value)) {
            return true
        }
      }
      
          // 전부 탐색했음에도 불구하고 찾지 못했다면 false를 반환합니다.
      return false;
    }
  }
BST : Binary Search Tree(이진 탐색 트리)
이진 트리 : 자식 노드가 최대 두개인 노드들로 구성된 트리
이진 탐색 트리 : 모든 왼쪽 자식의 값이 루트나 부모보다 작고, 모든 오른쪽 자식의 값이 루트나 부모보다 큰 값을 가지는 트리

Tree Traversal(트리 순회) -> Graph의 DFS에 포함된다.
Preorder(전위 순회)
- Root
 - Left
 - Right
 
순으로 순회
Inorder(중위 순회)
- Left
 - Root
 - Right
 
순으로 순회
Postorder(후위 순회)
- Left
 - Right
 - Root
 
순으로 순회
예제
class BinarySearchTree {
    constructor(value) {
          // constructor로 만든 객체는 이진 탐색 트리의 Node가 됩니다.
      this.value = value;
      this.left = null;
      this.right = null;
    }
  
      // 이진 탐색 트리의 삽입하는 메서드를 만듭니다.
    insert(value) {
          // 입력값을 기준으로, 현재 노드의 값보다 크거나 작은 것에 대한 조건문이 있어야 합니다.
          // 보다 작다면, Node의 왼쪽이 비어 있는지 확인 후 값을 넣습니다.
      if (value < this.value) {
        if (this.left === null) {
          this.left = new BinarySearchTree(value);
        } else {
          return this.left.insert(value);
        }
          // 보다 크다면, Node의 오른쪽이 비어 있는지 확인 후 값을 넣습니다.
      } else if (value > this.value) {
        if (this.right === null) {
          this.right = new BinarySearchTree(value);
        } else {
          return this.right.insert(value);
        }
          //그것도 아니라면, 입력값이 트리에 들어 있는 경우입니다.
      } else {
        // 아무것도 하지 않습니다.
        return
      }
    }
      // 이진 탐색 트리 안에 해당 값이 포함되어 있는지 확인하는 메서드를 만듭니다.
    contains(value) {
      if (this.value === value) {
        return true;
      }
          // 입력값을 기준으로 현재 노드의 값보다 작은지 판별하는 조건문이 있어야 합니다.
      if (value < this.value) {
        if(this.left && this.left.contains(value)) {
          return true;
        }
      }
          // 입력값을 기준으로 현재 노드의 값보다 큰지 판별하는 조건문이 있어야 합니다.
      if (value > this.value) {
              if(this.right && this.right.contains(value)) {
          return true;
        }
      }
          // 없다면 false를 반환합니다.
      return false
    }
  
      /*
      트리의 순회에 대해 구현을 합니다.
    지금 만드려고 하는 이 순회 메서드는 단지 순회만 하는 것이 아닌, 함수를 매개변수로 받아 콜백 함수에 값을 적용시킨 것을 순회해야 합니다.
    전위 순회를 통해 어떻게 탐색하는지 이해를 한다면 중위와 후위 순회는 쉽게 다가올 것입니다.
      */
  
      // 이진 탐색 트리를 전위 순회하는 메서드를 만듭니다.
    preorder(callback) {
          callback(this.value); //root
      if (this.left) {
        this.left.preorder(callback);
      };
      if (this.right) {
        this.right.preorder(callback);
      };
    }
  
      // 이진 탐색 트리를 중위 순회하는 메서드를 만듭니다.
    inorder(callback) {
      if (this.left) {
        this.left.inorder(callback);
      };
      callback(this.value) //root
      if (this.right) {
        this.right.inorder(callback);
      };
    }
  
      // 이진 탐색 트리를 후위 순회하는 메서드를 만듭니다.
    postorder(callback) {
      if (this.left) {
        this.left.postorder(callback);
      };
      if (this.right) {
        this.right.postorder(callback);
      };
      callback(this.value) //root
    }
  
  }
  
  const rootNode = new BinarySearchTree(10);
  rootNode.insert(7);
  rootNode.insert(8);
  rootNode.insert(12);
  rootNode.insert(11);
  console.log(rootNode.left.right.value); // 8
  console.log(rootNode.right.left.value); //11
  
  let arr = [];
  rootNode.preorder((value) => arr.push(value * 2));
  console.log(arr); // [20, 14, 16, 24, 22]
본 포스팅은 코드스테이츠 BEB 과정을 수강하며 작성한 글입니다.