๐Ÿ“š Binary Tree

๐Ÿ“š Binary Tree(์ด์ง„ ํŠธ๋ฆฌ)

  • ๊ฐ ๋…ธ๋“œ๊ฐ€ ์ตœ๋Œ€ ๋‘ ๊ฐœ์˜ ์ž์‹ ๋…ธ๋“œ๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋Š” ํŠธ๋ฆฌ ๊ตฌ์กฐ

๐Ÿ”Ž ์ด์ง„ ํŠธ๋ฆฌ์˜ ๊ธฐ๋ณธ ๊ฐœ๋…

  • ๋…ธ๋“œ(Node)
    • ๊ฐ’(val) : ๋…ธ๋“œ์— ์ €์žฅ๋œ ๋ฐ์ดํ„ฐ
    • ์™ผ์ชฝ ์ž์‹(left) : ์™ผ์ชฝ ์„œ๋ธŒํŠธ๋ฆฌ๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ํฌ์ธํ„ฐ
    • ์˜ค๋ฅธ์ชฝ ์ž์‹(right) : ์˜ค๋ฅธ์ชฝ ์„œ๋ธŒํŠธ๋ฆฌ๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ํฌ์ธํ„ฐ
  • ์ฃผ์š” ์šฉ์–ด
    • ๋ฃจํŠธ(root) : ํŠธ๋ฆฌ์˜ ์‹œ์ž‘์ (์ตœ์ƒ์œ„ ๋…ธ๋“œ)
    • ๋ถ€๋ชจ(parent) : ํŠน์ • ๋…ธ๋“œ๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ์ƒ์œ„ ๋…ธ๋“œ
    • ์ž์‹(child) : ๋ถ€๋ชจ ๋…ธ๋“œ์—์„œ ์—ฐ๊ฒฐ๋œ ํ•˜์œ„ ๋…ธ๋“œ
    • ๋ฆฌํ”„(leaf) : ์™ผ์ชฝ, ์˜ค๋ฅธ์ชฝ ์ž์‹์ด ์—†๋Š” ๋…ธ๋“œ
    • ๊นŠ์ด(depth) : ๋ฃจํŠธ์—์„œ ํŠน์ • ๋…ธ๋“œ๊นŒ์ง€์˜ ๊ฑฐ๋ฆฌ
    • ๋†’์ด(height) : ํŠน์ • ๋…ธ๋“œ์—์„œ ๊ฐ€์žฅ ๊นŠ์€ ๋ฆฌํ”„๊นŒ์ง€์˜ ๊ฑฐ๋ฆฌ

๐Ÿ’ป C++์—์„œ ์ด์ง„ ํŠธ๋ฆฌ ๊ตฌํ˜„

  • ๋ณดํ†ต ๊ตฌ์กฐ์ฒด(struct) ๋˜๋Š” ํด๋ž˜์Šค(class)๋กœ ๊ตฌํ˜„ํ•œ๋‹ค.

๐Ÿ“Œ ์ด์ง„ ํŠธ๋ฆฌ์˜ ๋…ธ๋“œ ๊ตฌ์กฐ

#include <iostream>
using namespace std;

// ์ด์ง„ ํŠธ๋ฆฌ ๋…ธ๋“œ ์ •์˜
struct TreeNode {
    int val;            // ๋…ธ๋“œ์˜ ๊ฐ’
    TreeNode* left;     // ์™ผ์ชฝ ์ž์‹
    TreeNode* right;    // ์˜ค๋ฅธ์ชฝ ์ž์‹

    // ๊ธฐ๋ณธ ์ƒ์„ฑ์ž
    TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};

๐Ÿ“Œ ์ด์ง„ ํŠธ๋ฆฌ ์ƒ์„ฑํ•ด๋ณด๊ธฐ

#include <iostream>
using namespace std;

struct TreeNode {
    int val;
    TreeNode* left;
    TreeNode* right;

    TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};

int main() {
    // ๋…ธ๋“œ ์ƒ์„ฑ
    TreeNode* root = new TreeNode(1);
    root->left = new TreeNode(2);
    root->right = new TreeNode(3);
    root->left->left = new TreeNode(4);
    root->left->right = new TreeNode(5);

    return 0;
}
  • TreeNode์˜ ๊ตฌ์กฐ์ฒด๋ฅผ ์ƒ์„ฑํ•œ ๋‹ค์Œ ๋ฃจํŠธ ๋…ธ๋“œ์™€ ๊ทธ ์ž์‹๋“ค์„ ์—ฐ๊ฒฐ์‹œ์ผœ์ฃผ๋ฉดโ€ฆ
        1
       / \
      2   3
     / \
    4   5
  • ์ตœ์ข…์ ์œผ๋กœ ์œ„์˜ ์ฝ”๋“œ๋กœ ๋งŒ๋“  ์ด์ง„ ํŠธ๋ฆฌ๋Š” ์ด๋Ÿฌํ•œ ํ˜•ํƒœ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค.

๐Ÿ“š ์ด์ง„ ํŠธ๋ฆฌ ์ˆœํšŒ(Tree Traversal)

  • ์ด์ง„ ํŠธ๋ฆฌ๋ฅผ ์ˆœํšŒํ•˜๋Š” ๋ฐฉ๋ฒ•์—๋Š” 4๊ฐ€์ง€๊ฐ€ ์กด์žฌํ•œ๋‹ค.
  1. ์ „์œ„ ์ˆœํšŒ(preorder) : root -> left -> right
  2. ์ค‘์œ„ ์ˆœํšŒ(inorder) : left -> root -> right
  3. ํ›„์œ„ ์ˆœํšŒ(postorder) : left -> right ->root;
  4. ๋ ˆ๋ฒจ ์ˆœํšŒ(level order) : BFS ๋ฐฉ์‹(queue ์‚ฌ์šฉ)

๐Ÿ’ป 4๊ฐ€์ง€ ์ˆœํšŒ ์ฝ”๋“œ ๋ฐฉ๋ฒ•

๐Ÿš€ ์ „์œ„ ์ˆœํšŒ

  • root -> left -> right ๋ฐฉ๋ฌธ ์ˆœ์„œ
void preorder(TreeNode* root) {
    if(!root)   return;
    cout << root->val << " "; // ํ˜„์žฌ ๋…ธ๋“œ ๋ฐฉ๋ฌธ
    preorder(root->left);   // ์™ผ์ชฝ ์„œ๋ธŒ ํŠธ๋ฆฌ ๋ฐฉ๋ฌธ
    preorder(root->right)   // ์˜ค๋ฅธ์ชฝ ์„œ๋ธŒ ํŠธ๋ฆฌ ๋ฐฉ๋ฌธ
}

๐Ÿš€ ์ค‘์œ„ ์ˆœํšŒ

  • left -> root -> right ๋ฐฉ๋ฌธ ์ˆœ์„œ
void inorder(TreeNode* root) {
    if(!root)   return;
    inorder(root->left);    //์™ผ์ชฝ ์„œ๋ธŒ ํŠธ๋ฆฌ ๋ฐฉ๋ฌธ
    cout<< root->val << " ";    // ํ˜„์žฌ ๋…ธ๋“œ ๋ฐฉ๋ฌธ
    inorder(root->right);   // ์˜ค๋ฅธ์ชฝ ์„œ๋ธŒ ํŠธ๋ฆฌ ๋ฐฉ๋ฌธ
}

๐Ÿš€ ํ›„์œ„ ์ˆœํšŒ

  • left -> right -> root ๋ฐฉ๋ฌธ ์ˆœ์„œ
void postorder(TreeNode* root)  {
    if(!root)   return;
    postorder(root->left);  // ์™ผ์ชฝ ์„œ๋ธŒ ํŠธ๋ฆฌ ๋ฐฉ๋ฌธ
    postorder(root->right); // ์˜ค๋ฅธ์ชฝ ์„œ๋ธŒ ํŠธ๋ฆฌ ๋ฐฉ๋ฌธ
    cout<< root->val << " ";    // ํ˜„์žฌ ๋…ธ๋“œ ๋ฐฉ๋ฌธ
}

๐Ÿš€ ๋ ˆ๋ฒจ ์ˆœํšŒ(BFS)

  • queue๋ฅผ ์ด์šฉํ•˜์—ฌ ๊ฐ ๋ ˆ๋ฒจ ๋…ธ๋“œ๋ฅผ ์ „๋ถ€ ๋ฐฉ๋ฌธํ•˜๋ฉฐ ๋‚ด๋ ค๊ฐ„๋‹ค.
void BFS(TreeNode* root) {
    if(!root)   return;

    queue(TreeNode*) q;
    q.push(root);

    while(!q.empty())
    {
        TreeNode* node = q.front();
        q.pop();
        
        cout << node->val << " ";

        if (node->left) q.push(node->left);
        if (node->right) q.push(node->right);
    }
}

๐Ÿ“š ์ด์ง„ ํƒ์ƒ‰ ํŠธ๋ฆฌ(Binary search Tree, BST)

  • ์™ผ์ชฝ ์ž์‹์€ ๋ถ€๋ชจ๋ณด๋‹ค ์ž‘๊ณ , ์˜ค๋ฅธ์ชฝ ์ž์‹์€ ๋ถ€๋ชจ๋ณด๋‹ค ํฐ ๊ฐ’์„ ๊ฐ€์ง€๋Š” ์ด์ง„ ํŠธ๋ฆฌ

๐Ÿ“Œ ์ด์ง„ ํƒ์ƒ‰ ํŠธ๋ฆฌ ์‚ฝ์ž…

TreeNode* insertBST(TreeNode* root, int val) {
    if (!root) return new TreeNode(val);
    
    if (val < root->val)
        root->left = insertBST(root->left, val);
    else
        root->right = insertBST(root->right, val);
    
    return root;
}

๐Ÿ“Œ ์ด์ง„ ํƒ์ƒ‰ ํŠธ๋ฆฌ ๊ฒ€์ƒ‰

  • ๊ฐ’์ด ๋” ์ž‘์•„์•ผํ•œ๋‹ค๋ฉด ์™ผ์ชฝ์œผ๋กœ ๋‚ด๋ ค๊ฐ€๋ฉด ๋˜๊ณ  ๊ฐ’์ด ๋” ์ปค์•ผํ•œ๋‹ค๋ฉด ์˜ค๋ฅธ์ชฝ์œผ๋กœ ๋‚ด๋ ค๊ฐ€์„œ ์ฐพ์œผ๋ฉด ๋œ๋‹ค.
bool searchBST(TreeNode* root, int val) {
    if (!root) return false;
    
    if (root->val == val) return true;
    else if (val < root->val) return searchBST(root->left, val);
    else return searchBST(root->right, val);
}

๐Ÿ”Ž ์™„์ „ ์ด์ง„ ํŠธ๋ฆฌ(Complete Binary Tree)

  • ๋ชจ๋“  ๋ ˆ๋ฒจ์—์„œ ์™ผ์ชฝ๋ถ€ํ„ฐ ์ฐจ๋ก€๋Œ€๋กœ ๋…ธ๋“œ๊ฐ€ ์ฑ„์›Œ์ง„ ์ด์ง„ ํŠธ๋ฆฌ์ด๋‹ค.

๐Ÿ“Œ ํŠน์ง•

  1. ์™ผ์ชฝ๋ถ€ํ„ฐ ์ฐจ๋ก€๋Œ€๋กœ ๋…ธ๋“œ๊ฐ€ ์ฑ„์›Œ์ ธ ์žˆ์–ด์•ผ ํ•œ๋‹ค.
  2. ๋งˆ์ง€๋ง‰ ๋ ˆ๋ฒจ์„ ์ œ์™ธํ•œ ๋ชจ๋“  ๋ ˆ๋ฒจ์—์„œ๋Š” ๋…ธ๋“œ๊ฐ€ ๊ฝ‰ ์ฐจ ์žˆ์–ด์•ผํ•œ๋‹ค.
  3. ์™ผ์ชฝ ์ž์‹์ด ์กด์žฌํ•˜์ง€ ์•Š๋Š”๋ฐ ์˜ค๋ฅธ์ชฝ ์ž์‹์ด ์กด์žฌํ•˜๋Š” ๊ฒฝ์šฐ๋Š” ์—†๋‹ค.

๐Ÿ“Š ํ˜•ํƒœ ์˜ˆ์‹œ

  • ์™„์ „ ์ด์ง„ ํŠธ๋ฆฌ(O)
         1
        / \
       2   3
      / \  /
     4   5 6
    
  • ์™„์ „ ์ด์ง„ ํŠธ๋ฆฌ(X)
       1
      / \
     2   3
    /     \
   4       5  โŒ (์™ผ์ชฝ์— 5๊ฐ€ ๋จผ์ € ์™€์•ผ ํ•จ)

๐Ÿ”‘ ์™„์ „ ์ด์ง„ ํŠธ๋ฆฌ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ๋ฌธ์ œ

์™„์ „ ์ด์ง„ ํŠธ๋ฆฌ ๋…ธ๋“œ ๊ฐœ์ˆ˜ ์ตœ์ ํ™” ๋ฌธ์ œ

  • ๋ณดํ†ต ์ด์ง„ ํŠธ๋ฆฌ์—์„œ ์ผ๋ฐ˜์ ์ธ ์žฌ๊ท€๋ฅผ ์‚ฌ์šฉํ•ด ์ˆซ์ž๋ฅผ ์„ธ๋ฉด ์‹œ๊ฐ„ ๋ณต์žก๋„๋Š” O(N) ์ด๋‹ค.
  • ํ•˜์ง€๋งŒ ์™„์ „ ์ด์ง„ ํŠธ๋ฆฌ ์—์„œ๋Š” ๋†’์ด ๋น„๊ต ์ตœ์ ํ™”๋ฅผ ํ†ตํ•ด O((logN)^2) ์œผ๋กœ ์ตœ์ ํ™”๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹ค.
  • ์™„์ „ ์ด์ง„ํŠธ๋ฆฌ์ด๊ณ  ๋†’์ด๊ฐ€ h์ผ ๋•Œ 2^(h+1) - 1 ์˜ ๊ณต์‹์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.