관리 메뉴

Daehyunii's Dev-blog

17 트리 순회 본문

πŸ“š Language & CS knowledge/Algorithm & Data structure

17 트리 순회

Daehyunii 2022. 8. 16. 20:16

17.1 트리 순회

  트리 μˆœνšŒλŠ” 말 κ·ΈλŒ€λ‘œ μ–΄λ–€ νŠΈλ¦¬μ—μ„œλ“ μ§€ μ‚¬μš©ν•  수 μžˆλŠ” κ°œλ…μ΄λ‹€. 예λ₯Ό λ“€μ–΄ 이진 탐색 νŠΈλ¦¬λ“ μ§€, κ·Έλƒ₯ 이진 νŠΈλ¦¬λ“ μ§€ κ·Έ μ™Έμ˜ μ–΄λ–€ νŠΈλ¦¬λ“€μ—λ„ λ‹€ μ‚¬μš©μ΄ κ°€λŠ₯ν•œ 순회 방법이닀. 즉 트리의 νŠΉμ„±μ„ 가지고 μžˆλ‹€λ©΄ 트리 순회λ₯Ό ν•  수 μžˆλ‹€. 트리λ₯Ό μˆœνšŒν•˜λŠ” λ°©λ²•μ—λŠ” λ§Žμ€ 방법이 μ‘΄μž¬ν•˜κ³  λŒ€ν‘œμ μœΌλ‘œ λ„ˆλΉ„ μš°μ„  탐색(Breadth First Search)κ³Ό κΉŠμ΄ μš°μ„  탐색(Deapth First Search)κ°€ μžˆλ‹€. μ–΄λ–€ 탐색 방법이든 λͺ¨λ“  λ…Έλ“œλ“€μ„ μˆœνšŒν•˜λŠ” 것은 λ™μΌν•˜λ‹€. 

 

17.2 λ„ˆλΉ„ μš°μ„  탐색

  λ„ˆλΉ„ μš°μ„  탐색(Breadth First Search)은 트리의 같은 λ ˆλ²¨μ— μžˆλŠ” λͺ¨λ“  λ…Έλ“œλ₯Ό 거쳐가며 순회λ₯Ό ν•˜λŠ” 방식이닀.

/*
트리)

           10
         /    \ 
        6      15
       / \     / \
      3	  8  12   20

λ„ˆλΉ„ μš°μ„  탐색) 같은 레벨의 λ…Έλ“œλ“€μ„ κ±°μ³κ°€λ©΄μ„œ 탐색

	------>10
   --->6----------->15
  3----->8----->12----->20
  
*/

  λ„ˆλΉ„ μš°μ„  탐색을 κ΅¬ν˜„ν•˜λ €λ©΄ 큐 자료 ꡬ쑰λ₯Ό μ΄μš©ν•΄μ•Ό ν•œλ‹€.(μ„ μž…μ„ μΆœ) 직접 큐 클래슀λ₯Ό λ§Œλ“€μ–΄μ„œ ν™œμš©ν•˜λŠ” 것보닀 배열을 ν™œμš©ν•΄μ„œ 큐λ₯Ό λ§Œλ“œλŠ” 것이 κ΅¬ν˜„ν•˜κΈ° 더 νŽΈλ¦¬ν•˜λ‹€.

 

β—Žμˆ˜λ„μ½”λ“œ

1) λ¨Όμ € λ³€μˆ˜ 두 개λ₯Ό λ§Œλ“ λ‹€.

2) 큐λ₯Ό λ§Œλ“€μ–΄μ„œ μš”μ†Œλ“€μ„ μΆ”μ ν•˜κ³ , 데이터λ₯Ό λ‹΄λŠ” 배열을 λ§Œλ“€μ–΄μ„œ λ§ˆμ§€λ§‰μ— λ°˜ν™˜ν•΄ μ€€λ‹€.

즉, λ§ˆμ§€λ§‰μ— 데이터λ₯Ό 담은 배열을 λ°˜ν™˜ν•˜κ³ , νλŠ” λ§ˆμ§€λ§‰μ—λŠ” λΉ„μ–΄ μžˆλŠ” λ°°μ—΄ μƒνƒœκ°€ λœλ‹€.(큐 배열은 κ·Έλƒ₯ λ„μ™€μ£ΌλŠ” μ—­ν• μž„)

3) μ²˜μŒμ—λŠ” 루트 λ…Έλ“œλ₯Ό 큐 배열에 λ„£κ³ , 큐 배열에 데이터가 μžˆλ‹€λ©΄ 계속 루프λ₯Ό λŒλ¦°λ‹€.

4) 그리고 νμ—μ„œ 디큐λ₯Ό ν•œλ‹€. 배열을 μ‚¬μš©ν•΄μ„œ λ§Œλ“œλŠ” κ²½μš°μ—λŠ” shift() λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•΄μ„œ 큐 λ°°μ—΄μ˜ 맨 μ•žμ— μžˆλŠ” 데이터λ₯Ό 제거 ν•œλ‹€.

5) 그리고 μ œκ±°ν•œ λ…Έλ“œμ˜ 값을 데이터λ₯Ό λ‹΄λŠ” 배열에 μΆ”κ°€ν•΄ μ€€λ‹€.

6) 그리고 제거된 λ…Έλ“œμ˜ μ™Όμͺ½/였λ₯Έμͺ½μ— λ…Έλ“œκ°€ μžˆλŠ”μ§€ ν™•μΈν•˜κ³  λ…Έλ“œκ°€ μžˆλ‹€λ©΄ ν•΄λ‹Ή λ…Έλ“œλ₯Ό 큐 배열에 λ‹΄λŠ”λ‹€.

7) λͺ¨λ“  루프가 λλ‚œ λ‹€μŒμ—λŠ” λͺ¨λ“  λ…Έλ“œμ˜ 값듀을 μ €μž₯ν•œ λ³€μˆ˜λ₯Ό 좜λ ₯ν•΄ μ€€λ‹€.

 

class Node {
    constructor(value){
        this.value = value;
        this.left = null;
        this.right = null;
    }
}

class BinarySearchTree {
    constructor(){
        this.root = null;
    }
    insert(value){
        var newNode = new Node(value);
        if(this.root === null){
            this.root = newNode;
            return this;
        }
        var current = this.root;
        while(true){
            if(value === current.value) return undefined;
            if(value < current.value){
                if(current.left === null){
                    current.left = newNode;
                    return this;
                }
                current = current.left;
            } else {
                if(current.right === null){
                    current.right = newNode;
                    return this;
                } 
                current = current.right;
            }
        }
    }
    
    find(value){
        if(this.root === null) return false;
        var current = this.root,
            found = false;
        while(current && !found){
            if(value < current.value){
                current = current.left;
            } else if(value > current.value){
                current = current.right;
            } else {
                found = true;
            }
        }
        if(!found) return undefined;
        return current;
    }

    BFS(){
        var node = this.root,
            data = [],
            queue = [];
        queue.push(node); 

        while(queue.length){ //빈 배열을 무쑰건 trueκ°€ λ‚˜μ™€μ„œ lengthλ₯Ό 이용
           node = queue.shift(); // shift 원본 λ°°μ—΄ 직접 λ³€κ²½(큐 λ°°μ—΄μ—μ„œ 제거됨)
           data.push(node.value); // push 원본 λ°°μ—΄ 직접 λ³€κ²½(데이타 배열에 좔가됨)
           if(node.left) queue.push(node.left);
           if(node.right) queue.push(node.right);
        }
        return data;    
    }
}

17.3 깊이 μš°μ„  탐색

  깊이 μš°μ„  탐색은 λ„ˆλΉ„ μš°μ„  탐색 처럼 ν˜•μ œλ…Έλ“œλ₯Ό λ‹€ κ±°μ³κ°€λ©΄μ„œ νƒμƒ‰ν•˜λŠ” 것이 μ•„λ‹ˆλΌ, 수직으둜 트리의 λκΉŒμ§€ λ‚΄λ €κ°€λ©΄μ„œ κ²€μƒ‰ν•˜λŠ” 것이닀. 깊이 μš°μ„  탐색은 μˆœνšŒμ‹œ 순회된 데이터λ₯Ό μ €μž₯ν•˜λŠ” 배열에 μ–Έμ œ 순회된 데이터λ₯Ό μ €μž₯할지에 따라 μ „μœ„ 순회, ν›„μœ„ 순회, μ€‘μœ„ 순회둜 λ‚˜λ‰  수 μžˆλ‹€.

 

β—Žμˆ˜λ„μ½”λ“œ

1) μˆœνšŒμ‹œ 확인을 ν•œ λ…Έλ“œλ“€μ˜ 값을 μ €μž₯ν•˜λŠ” 배열을 λ§Œλ“ λ‹€.

2) 맨 λ§ˆμ§€λ§‰μ—λŠ” 값을 μ €μž₯ν•œ 배열을 λ°˜ν™˜ν•œλ‹€.

3) ν˜„μž¬ ν™•μΈν•˜κ³  μžˆλŠ” λ…Έλ“œλ₯Ό κ°€λ¦¬ν‚€λŠ” 포인터 역할을 ν•  λ³€μˆ˜λ₯Ό λ§Œλ“€μ–΄ μ€€λ‹€. 그리고 트리의 λ£¨νŠΈλ…Έλ“œλ₯Ό ν• λ‹Ήν•œλ‹€.

4) 이제 헬퍼 ν•¨μˆ˜μΈ 쀑첩 ν•¨μˆ˜λ₯Ό λ§Œλ“ λ‹€. 

5) 이제 λ…Έλ“œλ“€μ„ λ°©λ¬Έν•΄μ„œ λ…Έλ“œλ“€μ˜ 값을 μ €μž₯ν•˜λŠ” 배열에 값을 μΆ”κ°€ν•΄ μ€€λ‹€.

6) 그리고 ν™•μΈν•œ λ…Έλ“œκ°€ μ™Όμͺ½/였λ₯Έμͺ½ ν”„λ‘œνΌν‹°μ— λ…Έλ“œλ₯Ό 가지고 μžˆλ‹€λ©΄ μž¬κ·€ λ°©μ‹μœΌλ‘œ 헬퍼 ν•¨μˆ˜λ₯Ό λ‹€μ‹œ ν˜ΈμΆœν•©λ‹ˆλ‹€.

 

class Node {
    constructor(value){
        this.value = value;
        this.left = null;
        this.right = null;
    }
}

class BinarySearchTree {
    constructor(){
        this.root = null;
    }
    insert(value){
        var newNode = new Node(value);
        if(this.root === null){
            this.root = newNode;
            return this;
        }
        var current = this.root;
        while(true){
            if(value === current.value) return undefined;
            if(value < current.value){
                if(current.left === null){
                    current.left = newNode;
                    return this;
                }
                current = current.left;
            } else {
                if(current.right === null){
                    current.right = newNode;
                    return this;
                } 
                current = current.right;
            }
        }
    }
    find(value){
        if(this.root === null) return false;
        var current = this.root,
            found = false;
        while(current && !found){
            if(value < current.value){
                current = current.left;
            } else if(value > current.value){
                current = current.right;
            } else {
                found = true;
            }
        }
        if(!found) return undefined;
        return current;
    }

    DFSPreOrder(){ //μ „μœ„
        var data = [];
        function traverse(node){
            data.push(node.value); // <--ν•΄λ‹Ή μ½”λ“œμ˜ μœ„μΉ˜μ— 따라 dfs의 μœ ν˜•μ΄ 달라진닀.
            if(node.left) traverse(node.left);
            if(node.right) traverse(node.right);
        }
        traverse(this.root);
        return data;
    }
    DFSPostOrder(){ //ν›„μœ„
        var data = [];
        function traverse(node){
            if(node.left) traverse(node.left);
            if(node.right) traverse(node.right);
            data.push(node.value); // <--ν•΄λ‹Ή μ½”λ“œμ˜ μœ„μΉ˜μ— 따라 dfs의 μœ ν˜•μ΄ 달라진닀.
        }
        traverse(this.root);
        return data;
    }
    DFSInOrder(){ //μ€‘μœ„
        var data = [];
        function traverse(node){
            if(node.left) traverse(node.left);
            data.push(node.value); // <--ν•΄λ‹Ή μ½”λ“œμ˜ μœ„μΉ˜μ— 따라 dfs의 μœ ν˜•μ΄ 달라진닀.
            if(node.right) traverse(node.right);
        }
        traverse(this.root);
        return data;
    }
}

  κ·Έλ ‡λ‹€λ©΄ λ„ˆλΉ„ μš°μ„  탐색, 깊이 μš°μ„  탐색은 μ–Έμ œ μ‚¬μš©ν•˜λ©΄ μ’‹μ„κΉŒ? μš°μ„  트리의 λ„ˆλΉ„κ°€ 넓은 κ²½μš°μ—λŠ” 깊이 μš°μ„  탐색 방법이 더 μœ λ¦¬ν•˜λ‹€. μ™œλƒν•˜λ©΄ λ„ˆλΉ„ μš°μ„  탐색은 큐에 μ €μž₯ν•΄μ„œ 그것을 ν™œμš©ν•˜λŠ” λ°©μ‹μœΌλ‘œ 이뀄지기 λ•Œλ¬Έμ— 넓이가 λ„“μ–΄ 질수둝 λ§Žμ€ 데이터λ₯Ό 큐에 μ €μž₯ν•΄μ•Ό ν•˜λ―€λ‘œ 곡간 λ³΅μž‘λ„κ°€ μ˜¬λΌκ°€κΈ° λ•Œλ¬Έμ΄λ‹€. λ°˜λŒ€λ‘œ 트리의 κΉŠμ΄κ°€ κΉŠμ€ κ²½μš°μ—λŠ” λ„ˆλΉ„ μš°μ„  탐색 방법이 μœ λ¦¬ν•˜λ‹€. 깊이 μš°μ„  탐색은 헬퍼 ν•¨μˆ˜κ°€ μž¬κ·€ ν˜ΈμΆœλ˜λŠ”λ° κΉŠμ΄κ°€ κΉŠμ–΄μ§€λ©΄ κ·Έ 만큼 콜 μŠ€νƒμ΄ κ³„μ†ν•΄μ„œ μŒ“μ΄κΈ° λ•Œλ¬Έμ΄λ‹€.

'πŸ“š Language & CS knowledge > Algorithm & Data structure' μΉ΄ν…Œκ³ λ¦¬μ˜ λ‹€λ₯Έ κΈ€

19 ν•΄μ‹œ ν…Œμ΄λΈ”  (0) 2022.08.16
18 이진 νž™  (0) 2022.08.16
16 이진 검색 트리  (0) 2022.08.14
15 μŠ€νƒ & 큐  (0) 2022.08.14
14 이쀑 μ—°κ²° 리슀트  (0) 2022.08.13