๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

๐Ÿค– data structures & algorithms

Data Structures & Algorithms with Javascript : Binary Trees and Binary Search Trees

2024.07.24 - [๐Ÿค– data structures & algorithms] - Data Structures & Algorithms with Javascript : Sets

 

Data Structures & Algorithms with Javascript : Sets

[์ด์ „ ๊ธ€]2024.07.23 - [๐Ÿค– data structures & algorithms] - Data Structures & Algorithms with Javascript : Hashing Data Structures & Algorithms with Javascript : Hashing[์ด์ „ ๊ธ€] 2024.07.22 - [๐Ÿค– data structures & algorithms] - Data Structures & A

pyotato-dev.tistory.com

๐ŸŒฒ ํŠธ๋ฆฌ๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๊ณ„์ธต์ ์œผ๋กœ ๋‚˜ํƒ€๋‚ผ ๋•Œ ์œ ์šฉํ•œ ๋น„์„ ํ˜• ์ž๋ฃŒ ๊ตฌ์กฐ๋‹ค.
ํŠธ๋ฆฌ ์ž๋ฃŒ ๊ตฌ์กฐ๋ฅผ ํŒŒ์ผ ์‹œ์Šคํ…œ์ด๋‚˜ ๋ฐ์ดํ„ฐ ๋ฆฌ์ŠคํŠธ๋ฅผ ์ •๋ ฌํ•˜๋Š”๋ฐ ์ข…์ข… ์“ฐ๊ณค ํ•œ๋‹ค.
์˜ค๋Š˜์€ ํŠธ๋ฆฌ ๊ตฌ์กฐ ์ค‘ "์ด์ง„ ํŠธ๋ฆฌ (binary tree)"์— ๋Œ€ํ•ด ์‚ดํŽด๋ณด์ž.
์ด์ง„ ํŠธ๋ฆฌ๋Š” linked list ๋ณด๋‹ค ๊ฒ€์ƒ‰์ด ๋น ๋ฅด๊ณ , array๋ณด๋‹ค ๋ฐ์ดํ„ฐ ์‚ฝ์ž…/์‚ญ์ œ๊ฐ€ ๋น ๋ฅด๊ธฐ ๋•Œ๋ฌธ์— ๋” ์„ ํ˜ธ๋˜๋Š”๋ฐ, 

๐Ÿ‘ฉ๐Ÿป‍๐Ÿ’ป ์ด์ง„ ํŠธ๋ฆฌ๊ฐ€ ๋ฌด์—‡์ธ์ง€ ์•Œ์•„๋ณด๊ณ , ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ class๋กœ ์ž๋ฃŒ ๊ตฌ์กฐ์™€ ์—ฐ์‚ฐ๋“ค์„ ๊ตฌํ˜„ํ•ด๋ณด์ž. 

๐ŸŒฒ  ํŠธ๋ฆฌ ์ž๋ฃŒ ๊ตฌ์กฐ๋ž€?

ํŠธ๋ฆฌ ์ž๋ฃŒ ๊ตฌ์กฐ๋Š” node์™€ edge๋กœ ์ด๋ฃจ์–ด์ ธ ์žˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ๋‹ค์Œ ๊ทธ๋ฆผ์˜ ์กฐ์ง ๊ด€๊ณ„๋„๋Š” ํŠธ๋ฆฌ ๊ตฌ์กฐ๋กœ ๋˜์–ด ์žˆ๋‹ค.

๊ฐ ์งํ•จ์€ node๋ฅผ ๋‚˜ํƒ€๋‚ด๊ณ , ๊ฐ ์งํ•จ์˜ ๊ด€๊ณ„๊ฐ€ edge์— ํ•ด๋‹น๋œ๋‹ค.

CIO๋Š” CEO์— ์ง์ ‘ ๋ณด๊ณ ๋ฅผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— edge๋กœ ์—ฐ๊ฒฐ๋˜์–ด ์žˆ๊ณ , VP์™€ CEO๋˜ํ•œ ๊ฐ™์€ ๊ด€๊ณ„์ด๋ฏ€๋กœ edge๋กœ ์—ฐ๊ฒฐ๋˜์–ด ์žˆ๋‹ค.

ํ•˜์ง€๋งŒ VP sales์™€ development manager๋Š” ์„œ๋กœ ๋ณด๊ณ ๋ฅผ ์ง์ ‘ ์ฃผ๊ณ  ๋ฐ›๋Š” ์‚ฌ์ด๊ฐ€ ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌด๋„ค edge๋กœ ์—ฐ๊ฒฐ๋˜์–ด ์žˆ์ง€ ์•Š๊ณ , ์ง์ ‘ ๊ด€๋ จ์ด ์žˆ๋Š” ๋ถ€์„œ๊ฐ€ ์•„๋‹ˆ๋ผ๊ณ  ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

์กฐ์ง ๊ด€๊ณ„๋„๋„ ํŠธ๋ฆฌ ์ž๋ฃŒ๊ตฌ์กฐ๋‹ค.

 

ํŠธ๋ฆฌ์˜ ๊ตฌ์„ฑ์š”์†Œ๋ฅผ ๋” ์ž์„ธํžˆ ์‚ดํŽด๋ณด๊ธฐ ์œ„ํ•ด ๋‹ค์Œ์˜ ํŠธ๋ฆฌ๋ฅผ ์‚ดํŽด๋ณด์ž.

ํŠธ๋ฆฌ ๊ตฌ์กฐ์—์„œ level, root, path, subtree, key,leaf๊ฐ€ ๊ฐ๊ฐ ์–ด๋–ค ๊ฒƒ๋“ค์— ํ•ด๋‹น๋˜๋‚˜?

ํŠธ๋ฆฌ๋Š” ๊ณ„์ธต ๊ตฌ์กฐ๋ฅผ ์ง€๋‹Œ ๋ฐ์ดํ„ฐ๋ผ๊ณ  ์•ž์„œ ์ด์•ผ๊ธฐํ–ˆ๋‹ค. ์œ„์˜ ๊ทธ๋ฆผ์ฒ˜๋Ÿฌ level๋กœ ๊ฐ ๊ณ„์ธต ๊ตฌ์กฐ๋ฅผ ๋‚˜ํƒ€๋‚ผ ์ˆ˜ ์žˆ๋‹ค.

๋ ˆ๋ฒจ 0์ธ ์ตœ์ƒ์œ„ ๋…ธ๋“œ๋Š” root๋ผ๊ณ ๋„ ๋ถˆ๋ฆฐ๋‹ค. ๋ฃจํŠธ ๋…ธ๋“œ ์•„๋ž˜์— ๋…ธ๋“œ๋“ค์ด ์žˆ๋Š”๋ฐ, ์ด ๋…ธ๋“œ๋“ค์„ child (์ž์‹) ๋…ธ๋“œ๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค. 

๊ทธ๋ฆฌ๊ณ  child ๋…ธ๋“œ ์ƒ์œ„์˜ ๋…ธ๋“œ๋ฅผ parent (๋ถ€๋ชจ) ๋…ธ๋“œ๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค. ์ž์‹ ๋…ธ๋“œ๊ฐ€ ์—†๋Š” ๋…ธ๋“œ๋Š” leaf ๋…ธ๋“œ๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค.

์˜ค๋Š˜์€ ํŠธ๋ฆฌ ์ค‘์—์„œ๋„ binary tree (์ด์ง„ ํŠธ๋ฆฌ)์— ๋Œ€ํ•ด์„œ ์‚ดํŽด๋ณผ ๊ฑด๋ฐ, ์ด์ง„ ํŠธ๋ฆฌ๋Š” ๋ชจ๋“  ๋…ธ๋“œ์˜ ์ž์‹ ๋…ธ๋“œ ๊ฐœ์ˆ˜๊ฐ€ 2๊ฐœ ์ดํ•˜์ธ ํŠธ๋ฆฌ๋ฅผ ์ผ์ปซ๋Š”๋‹ค. ๊ฐ ๋…ธ๋“œ๋Š” key๋ผ๊ณ ๋„ ๋ถˆ๋ฆฌ๋Š” ๊ฐ’์„ ์ง€๋‹ˆ๊ณ  ์žˆ๋‹ค. ํ•˜๋‚˜์˜ ๋…ธ๋“œ A๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์™ผ์ชฝ์— ์žˆ๋Š” ๊ฐ’์„ left child of A๋ผ๊ณ  ํ‘œํ˜„ํ•˜๊ณ , ์˜ค๋ฅธ์ชฝ์— ์žˆ๋Š” ์ž์‹ ๋…ธ๋“œ๋ฅผ right child of A๋ผ๊ณ  ํ•œ๋‹ค. 

 

๊ฐ ๋…ธ๋“œ์— ์ง์ ‘ ์—ฐ๊ฒฐ๋œ ๊ด€๊ณ„๋ฅผ edge๋ผ๊ณ  ํ–ˆ์—ˆ๋Š”๋ฐ, ํ•˜๋‚˜์˜ ๋…ธ๋“œ์—์„œ ๋‹ค๋ฅธ ๋…ธ๋“œ๋กœ ์ ‘๊ทผํ•˜๊ธฐ ์œ„ํ•œ ์ผ๋ จ์˜ edge๋“ค์„ path๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ๋ชจ๋“  ๋…ธ๋“œ๋ฅผ ํŠน์ • ์ˆœ์„œ์— ๋”ฐ๋ผ ๋ฐฉ๋ฌธํ•˜๋Š” ๊ณผ์ •์„ tree traversal(ํŠธ๋ฆฌ ์ˆœํšŒ)๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค.

๐ŸŒฒ  Binary Tree(์ด์ง„ํŠธ๋ฆฌ)์™€ Binary Search Tree(์ด์ง„ ํƒ์ƒ‰ ํŠธ๋ฆฌ)

์ด์ง„ ํŠธ๋ฆฌ๋Š” ์ž์‹ ๋…ธ๋“œ์˜ ๊ฐœ์ˆ˜๊ฐ€ 2๊ฐœ ์ดํ•˜๋กœ ์ œํ•œ๋œ ํŠธ๋ฆฌ ๊ตฌ์กฐ๋ผ๋Š” ๊ฒƒ์„ ์‚ดํŽด๋ดค๋‹ค.

์ž์‹ ๋…ธ๋“œ์˜ ๊ฐœ์ˆ˜๋ฅผ ์ตœ๋Œ€ 2๊ฐœ๋กœ ์ œํ•œํ•˜๋ฉด ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฝ์ž…, ์‚ญ์ œ ๊ทธ๋ฆฌ๊ณ  ๊ฒ€์ƒ‰ํ•˜๋Š” ๊ณผ์ •์ด ํšจ์œจ์ ์ด๋‹ค.

์™œ๋ƒํ•˜๋ฉด ๊ฐ’์„ ์™ผ์ชฝ ๋˜๋Š” ์˜ค๋ฅธ์ชฝ ๋…ธ๋“œ๋กœ๋งŒ ์ €์žฅํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

์ด์ง„ ํŠธ๋ฆฌ ๊ตฌ์กฐ

์ด์ง„ ํƒ์ƒ‰ ํŠธ๋ฆฌ๋Š” ์ž์‹ ๋…ธ๋“œ๋ฅผ ๋” ์ƒ์„ธํ•œ ๋ถ„๋ฅ˜ ๊ธฐ์ค€์œผ๋กœ ์ €์žฅํ•œ ์ด์ง„ ํŠธ๋ฆฌ๋‹ค.

์ด์ง„ ํƒ์ƒ‰ ํŠธ๋ฆฌ๋Š” 2๊ฐœ ์ดํ•˜์˜ ์ž์‹ ๋…ธ๋“œ๋ฅผ ๊ฐ–๋Š” ๊ฒƒ๊ณผ ํ•จ๊ป˜, ํ•ญ์ƒ ์ž‘์€ ํ‚ค ๊ฐ’์ด ์™ผ์ชฝ์— ์žˆ๊ณ , ์˜ค๋ฅธ์ชฝ์œผ๋กœ ๊ฐˆ์ˆ˜๋ก ํฐ ๊ฐ’์œผ๋กœ ์ด๋ฃจ์–ด์ง„๋‹ค.

๐Ÿ” ์ด์ง„ ํƒ์ƒ‰ ํŠธ๋ฆฌ(BST) ๊ตฌํ˜„

์ด์ง„ ํƒ์ƒ‰ ํŠธ๋ฆฌ๋Š” ๋…ธ๋“œ๋กœ ๊ตฌ์„ฑ๋œ๋‹ค. ๋จผ์ € ๋…ธ๋“œ ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค์–ด ๋ณด์ž. ๋…ธ๋“œ ํด๋ž˜์Šค๋Š” linked list์™€ ์œ ์‚ฌํ•œ ๊ตฌ์กฐ๋‹ค.

โ€ผ ์˜ˆ์ œ๋Š” ์ฑ…์˜ ๊ตฌํ˜„์„ ์ฐธ๊ณ ํ•˜์—ฌ ํด๋ž˜์Šค๋กœ ์žฌ๊ตฌ์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค!!

 

Node ํด๋ž˜์Šค๋Š” ์™ผ์ชฝ ์˜ค๋ฅธ์ชฝ์— ์ €์žฅํ•  ๋…ธ๋“œ ์ฐธ์กฐ์™€ ํ˜„์žฌ ๋…ธ๋“œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด์—ฌ์ค„ show ๋ฉ”์„œ๋“œ๋กœ ๊ตฌ์„ฑ๋œ๋‹ค.

class Node{
	constructor(data, left, right){
		this.data = data;
        this.left = left;
        this.right = right;
	}
    
    // ํ˜„์žฌ ๋…ธ๋“œ์˜ ๋ฐ์ดํ„ฐ ๋ณด์—ฌ์ฃผ๊ธฐ 
	show(){
    	return this.data;
    }
}

 

BST ํด๋ž˜์Šค๋Š” ๋ฃจํŠธ ๋…ธ๋“œ ๋ฉค๋ฒ„์™€ ๋…ธ๋“œ๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๋ฉ”์„œ๋“œ์ธ insert๋กœ ๊ตฌ์„ฑ๋œ๋‹ค.

class BST{
	constructor(){
    	this.root = null;
    }
    
    // ๋…ธ๋“œ ์ถ”๊ฐ€
	insert(data){
    	let n = new Node(data,null,null); // ์ถ”๊ฐ€ํ•  ๋…ธ๋“œ ์ƒ์„ฑ
        if(this.root == null){ // ๋ฃจํŠธ๊ฐ€ ๋น„์–ด ์žˆ๋‹ค๋ฉด ์ถ”๊ฐ€ํ•  ๋…ธ๋“œ๋ฅผ ๋ฃจํŠธ ๋…ธ๋“œ๋กœ ํ• ๋‹น
        	this.root = n;
        } else {
        	let current = this.root; // ๋ฃจํŠธ๊ฐ€ ๋น„์–ด ์žˆ์ง€ ์•Š๋‹ค๋ฉด ํ˜„์žฌ ๋ฃจํŠธ๋ฅผ ๊ธฐ์ค€์œผ๋กœ
            let parent;
            while(true){
            	parent = current;	// ๋ถ€๋ชจ๋ฅผ ํ˜„์žฌ ๋ฃจํŠธ ๋…ธ๋“œ๋กœ ํ•˜๊ณ 
                if(data < current.data){	// ํ˜„์žฌ ๋ฐ์ดํ„ฐ๊ฐ€ ๋ถ€๋ชจ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์ž‘๋‹ค๋ฉด
                	current = current.left; 
                    if(current == null){
                    	parent.left = n; // ๋ถ€๋ชจ ๋…ธ๋“œ ๊ธฐ์ค€ ์™ผ์ชฝ์— ํ• ๋‹นํ•œ๋‹ค
                        break;
                    }
                } else {
                	current = current.right; // ํ˜„์žฌ ๋ฐ์ดํ„ฐ๊ฐ€ ๋ถ€๋ชจ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ํฌ๋‹ค๋ฉด
                    if(current == null){	
                    	parent.right = n; // ๋ถ€๋ชจ ๋…ธ๋“œ ๊ธฐ์ค€์œผ๋กœ ์˜ค๋ฅธ์ชฝ์œผ๋กœ ํ• ๋‹น
                        break;
                    }
                }
            }
        
        }
    
    }
}

 

๐ŸŽ„  BST ์ˆœํšŒ

BST์— ๋…ธ๋“œ๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ์—ฐ์‚ฐ๊นŒ์ง€ ์‚ดํŽด๋ดค๋‹ค. ํŠธ๋ฆฌ๊ฐ€ ๊ณ„์ธต ๊ตฌ์กฐ๋ผ๋Š” ์ ์„ ์‚ด๋ ค์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณผ ์ˆ˜ ์žˆ์œผ๋ฉด ์ข‹์„ ๊ฑฐ ๊ฐ™๋‹ค.

BST๋ฅผ ์ˆœํšŒํ•˜๋Š” ๋ฐฉ์‹์—๋Š” 3๊ฐ€์ง€๊ฐ€ ์žˆ๋‹ค:

Inorder : ๋ชจ๋“  ๋…ธ๋“œ์˜ ํ‚ค๋ฅผ ์˜ค๋ฆ„์ฐจ์ˆœ์œผ๋กœ ๋ฐฉ๋ฌธ

inorder binary search tree traversal

Preorder : ๋ฃจํŠธ ๋จผ์ € ๋ฐฉ๋ฌธ => ๋ฃจํŠธ ๋…ธ๋“œ ์™ผ์ชฝ subtree ์ž์‹ ๋…ธ๋“œ๋“ค => ๋ฃจํŠธ ๋…ธ๋“œ ์˜ค๋ฅธ์ชฝ subtree ์ž์‹ ๋…ธ๋“œ๋“ค ๋ฐฉ๋ฌธ

preorder binary search tree traversal

 

Postorder : ์™ผ์ชฝ ๋ฆฌํ”„ ๋ฐฉ๋ฌธ =>ํ•ด๋‹น subtree ์ž์‹ ๋…ธ๋“œ ๋ฐฉ๋ฌธ => ์˜ค๋ฅธ์ชฝ subtree ์ž์‹ ๋…ธ๋“œ ๋ฐฉ๋ฌธ => ๋ฃจํŠธ ๋งจ ๋งˆ์ง€๋ง‰์— ๋ฐฉ๋ฌธ

postorder binary search tree traversal

๐Ÿ‘ฉ๐Ÿป‍๐Ÿ’ป  BST  ์ˆœํšŒ ๊ตฌํ˜„

์ˆœํšŒ ์ฝ”๋“œ๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ์žฌ๊ท€ํ•จ์ˆ˜๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ํ•œ๋‹ค. 

 

// inorder traversal
function inOrder(node){
    if(!(node == null)){
        inOrder(node.left);	
        print(node.show());
        inOrder(node.right);
    }
}

// preOrder traversal
function preOrder(node){
    	if(!(node == null)){
        	print(node.show());
        	preOrder(node.left);
			preOrder(node.right);
        }
    }
    
	// postOrder traversal
function postOrder(node){
    	if(!(node == null)){
        	postOrder(node.left);
			postOrder(node.right);
            print(node.show());
        }
    }

 

์ „์ฒด ์ฝ”๋“œ

class Node{
	constructor(data, left, right){
		this.data = data;
        this.left = left;
        this.right = right;
	}
    
    // ํ˜„์žฌ ๋…ธ๋“œ์˜ ๋ฐ์ดํ„ฐ ๋ณด์—ฌ์ฃผ๊ธฐ 
	show(){
    	return this.data;
    }
}

class BST{
	constructor(){
    	this.root = null;
    }
    
    // ๋…ธ๋“œ ์ถ”๊ฐ€
	insert(data){
    	let n = new Node(data,null,null); // ์ถ”๊ฐ€ํ•  ๋…ธ๋“œ ์ƒ์„ฑ
        if(this.root == null){ // ๋ฃจํŠธ๊ฐ€ ๋น„์–ด ์žˆ๋‹ค๋ฉด ์ถ”๊ฐ€ํ•  ๋…ธ๋“œ๋ฅผ ๋ฃจํŠธ ๋…ธ๋“œ๋กœ ํ• ๋‹น
        	this.root = n;
        } else {
        	let current = this.root; // ๋ฃจํŠธ๊ฐ€ ๋น„์–ด ์žˆ์ง€ ์•Š๋‹ค๋ฉด ํ˜„์žฌ ๋ฃจํŠธ๋ฅผ ๊ธฐ์ค€์œผ๋กœ
            let parent;
            while(true){
            	parent = current;	// ๋ถ€๋ชจ๋ฅผ ํ˜„์žฌ ๋ฃจํŠธ ๋…ธ๋“œ๋กœ ํ•˜๊ณ 
                if(data < current.data){	// ํ˜„์žฌ ๋ฐ์ดํ„ฐ๊ฐ€ ๋ถ€๋ชจ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์ž‘๋‹ค๋ฉด
                	current = current.left; 
                    if(current == null){
                    	parent.left = n; // ๋ถ€๋ชจ ๋…ธ๋“œ ๊ธฐ์ค€ ์™ผ์ชฝ์— ํ• ๋‹นํ•œ๋‹ค
                        break;
                    }
                } else {
                	current = current.right; // ํ˜„์žฌ ๋ฐ์ดํ„ฐ๊ฐ€ ๋ถ€๋ชจ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ํฌ๋‹ค๋ฉด
                    if(current == null){	
                    	parent.right = n; // ๋ถ€๋ชจ ๋…ธ๋“œ ๊ธฐ์ค€์œผ๋กœ ์˜ค๋ฅธ์ชฝ์œผ๋กœ ํ• ๋‹น
                        break;
                    }
                }
            }
        
        }
    
    }
}

// ์ถœ๋ ฅ ์œ ํ‹ธ ํ•จ์ˆ˜
function print(item){
		console.log(item);
}

// inorder traversal
function inOrder(node){
    if(!(node == null)){
        inOrder(node.left);
        print(node.show());
        inOrder(node.right);
    }
}
	// preOrder traversal
function preOrder(node){
    	if(!(node == null)){
        	print(node.show());
        	preOrder(node.left);
			preOrder(node.right);
        }
    }
    
	// postOrder traversal
function postOrder(node){
    	if(!(node == null)){
        	postOrder(node.left);
			postOrder(node.right);
            print(node.show());
        }
    }
  
let nums = new BST();
nums.insert(23);
nums.insert(45);
nums.insert(16);
nums.insert(37);
nums.insert(3);
nums.insert(99);
nums.insert(22);
print("Inorder traversal:");
inOrder(nums.root);
print("Preorder traversal:");
preOrder(nums.root);
print("Postorder traversal:");
postOrder(nums.root);

 

์ˆœํšŒ ๊ฒฐ๊ณผ ์‚ดํŽด๋ณด๊ธฐ

/**
Inorder traversal:
3
16
22
23
37
45
99
Preorder traversal:
23
16
3
22
45
37
99
Postorder traversal:
3
22
16
37
99
45
23 
*/

 

ํŠธ๋ฆฌ ๋…ธ๋“œ ์ถ”๊ฐ€ ๊ณผ์ •

let nums = new BST();

nums.insert(23);                   ----->            root [23]
                                                                                      \ 
nums.insert(45);                                                         [45]

nums.insert(16);                                          root [23]
                                                                         /         \ 
                                                                   [16]          [45]
                                                                                  /  
nums.insert(37);                                                 [37]

nums.insert(3);                                            root [23]        
                                                                         /      \
                                                                    [16]       [45]
                                                                    /             /
                                                                [3]          [37]                          

nums.insert(99);                                        root [23]
                                                                        /      \
                                                                      [16]    [45]
                                                                     /            /     \                                 
                                                                  [3]        [37]   [99]                                                                                                

nums.insert(22);                                            root [23]
                                                                        /             \
                                                                    [16]           [45]
                                                                     /   \             /      \                 
                                                                 [3]     [22]    [37]  [99]                                                                           


ํŠธ๋ฆฌ ์ˆœํšŒ ๊ณผ์ •

          root [23]        
   a    /             \   b      
      [16]           [45] 
c    /   \ d       e  /      \ f                  
[3]     [22]    [37]  [99] 


Inorder traversal:
      path :       c  =>    d   =>    a    =>    e   =>    f  
๋…ธ๋“œ ๋ฐฉ๋ฌธ :  [3] [16] [22] [23] [37] [45] [99]

Preorder traversal: 
      path :       a   =>    c   =>    d    =>    e   =>    f  
๋…ธ๋“œ ๋ฐฉ๋ฌธ :  [23] [16] [3] [22] [45] [37] [99]
Postorder traversal: 
      path :       c   =>    d    =>    e    =>    f    =>    a
๋…ธ๋“œ ๋ฐฉ๋ฌธ :   [3] [22] [16] [37] [99] [45] [23]

 

inorder, preorder, postorder ์ˆœํšŒ ๋น„๊ต

inorder, preorder,postorder bst traversal

๐Ÿ”  BST ํƒ์ƒ‰

bst ํƒ์ƒ‰์— ์ฃผ๋กœ ํ™œ์šฉ๋˜๋Š” ์˜ˆ๋Š” ํฌ๊ฒŒ ๋‹ค์Œ 3๊ฐ€์ง€ ๊ฒฝ์šฐ๊ฐ€ ์žˆ๋‹ค 

  1. ํŠน์ • ๊ฐ’ ์ฐพ๊ธฐ
  2. ์ตœ์†Œ ๊ฐ’ ์ฐพ๊ธฐ
  3. ์ตœ๋Œ€ ๊ฐ’ ์ฐพ๊ธฐ

์ตœ๋Œ€/์ตœ์†Œ ๊ฐ’ ์ฐพ๊ธฐ

BST์—์„œ ์ตœ๋Œ€/์ตœ์†Œ๊ฐ’์€ ๋น„๊ต์  ๊ฐ„๋‹จํ•œ ๋ฐฉ์‹์œผ๋กœ ์ €์žฅ๋œ๋‹ค.

๊ฐ’์ด ์ž‘์„ ์ˆ˜๋ก ์™ผ์ชฝ ์ž์‹ ๋…ธ๋“œ์— ์ €์žฅ๋˜๊ธฐ ๋•Œ๋ฌธ์— BSt์˜ ์ตœ์†Œ๊ฐ’์„ ์ฐพ๊ธฐ ์œ„ํ•ด์„œ๋Š”

BST์˜ ์™ผ์ชฝ edge๋ฅผ ์ˆœํšŒํ•˜๋ฉด์„œ ๋งจ ๋งˆ์ง€๋ง‰ ๋…ธ๋“œ๋ฅผ ์ฐพ์œผ๋ฉด ๋œ๋‹ค.

 

์ตœ์†Œ ๊ฐ’์„ ๊ตฌํ•˜๊ธฐ ์œ„ํ•œ ๋ฉ”์„œ๋“œ getMin()๋ฅผ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ตฌํ˜„ํ•ด๋ณผ ์ˆ˜ ์žˆ๋‹ค.

getMin(){
	let current = this.root;			// ๋ฃจํŠธ ๋…ธ๋“œ๋กœ๋ถ€ํ„ฐ ์‹œ์ž‘ํ•ด์„œ 
    while(!(current.left == null)){		// ๋” ์ด์ƒ ์™ผ์ชฝ ์ž์‹ ๋…ธ๋“œ๊ฐ€ ์—†์„ ๋•Œ๊นŒ์ง€ ๊ฒ€์ƒ‰
    	current = current.left;
    }
    return current.data;		// ๋งจ ์™ผ์ชฝ์˜ leaf ๋…ธ๋“œ๊ฐ€ ๊ฐ€์žฅ ์ž‘์€ ๊ฐ’์ด๋ฏ€๋กœ ๋ฆฌํ„ด
}

 

์ตœ๋Œ€ ๊ฐ’์€ ๋ฐ˜๋Œ€๋กœ ๊ฐ€์žฅ ์˜ค๋ฅธ์ชฝ์˜ leaf ๋…ธ๋“œ๋ฅผ ์ฐพ์œผ๋ฉด ๋œ๋‹ค.

getMax(){
	let current = this.root;
    while(!(current.right == null)){
    	current = current.right;
    }
	return current.data;
}

 

๐Ÿ‘‡ ์ „์ฒด ์ฝ”๋“œ!

๋”๋ณด๊ธฐ

 

class Node{
	constructor(data, left, right){
		this.data = data;
        this.left = left;
        this.right = right;
	}
    
    // ํ˜„์žฌ ๋…ธ๋“œ์˜ ๋ฐ์ดํ„ฐ ๋ณด์—ฌ์ฃผ๊ธฐ 
	show(){
    	return this.data;
    }
}

class BST{
	constructor(){
    	this.root = null;
    }
    
    // ๋…ธ๋“œ ์ถ”๊ฐ€
	insert(data){
    	let n = new Node(data,null,null); // ์ถ”๊ฐ€ํ•  ๋…ธ๋“œ ์ƒ์„ฑ
        if(this.root == null){ // ๋ฃจํŠธ๊ฐ€ ๋น„์–ด ์žˆ๋‹ค๋ฉด ์ถ”๊ฐ€ํ•  ๋…ธ๋“œ๋ฅผ ๋ฃจํŠธ ๋…ธ๋“œ๋กœ ํ• ๋‹น
        	this.root = n;
        } else {
        	let current = this.root; // ๋ฃจํŠธ๊ฐ€ ๋น„์–ด ์žˆ์ง€ ์•Š๋‹ค๋ฉด ํ˜„์žฌ ๋ฃจํŠธ๋ฅผ ๊ธฐ์ค€์œผ๋กœ
            let parent;
            while(true){
            	parent = current;	// ๋ถ€๋ชจ๋ฅผ ํ˜„์žฌ ๋ฃจํŠธ ๋…ธ๋“œ๋กœ ํ•˜๊ณ 
                if(data < current.data){	// ํ˜„์žฌ ๋ฐ์ดํ„ฐ๊ฐ€ ๋ถ€๋ชจ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์ž‘๋‹ค๋ฉด
                	current = current.left; 
                    if(current == null){
                    	parent.left = n; // ๋ถ€๋ชจ ๋…ธ๋“œ ๊ธฐ์ค€ ์™ผ์ชฝ์— ํ• ๋‹นํ•œ๋‹ค
                        break;
                    }
                } else {
                	current = current.right; // ํ˜„์žฌ ๋ฐ์ดํ„ฐ๊ฐ€ ๋ถ€๋ชจ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ํฌ๋‹ค๋ฉด
                    if(current == null){	
                    	parent.right = n; // ๋ถ€๋ชจ ๋…ธ๋“œ ๊ธฐ์ค€์œผ๋กœ ์˜ค๋ฅธ์ชฝ์œผ๋กœ ํ• ๋‹น
                        break;
                    }
                }
            }
        
        }
    
    }
	////////////////////////////////////////////////// ๐Ÿ’– ์ถ”๊ฐ€ ////////////////////////////////////////////////// 
    
    getMin(){
    	let current = this.root;			// ๋ฃจํŠธ ๋…ธ๋“œ๋กœ๋ถ€ํ„ฐ ์‹œ์ž‘ํ•ด์„œ 
            while(!(current.left == null)){		// ๋” ์ด์ƒ ์™ผ์ชฝ ์ž์‹ ๋…ธ๋“œ๊ฐ€ ์—†์„ ๋•Œ๊นŒ์ง€ ๊ฒ€์ƒ‰
            	current = current.left;
            }
        return current.data;		// ๋งจ ์™ผ์ชฝ์˜ leaf ๋…ธ๋“œ๊ฐ€ ๊ฐ€์žฅ ์ž‘์€ ๊ฐ’์ด๋ฏ€๋กœ ๋ฆฌํ„ด
    }


  getMax(){
	let current = this.root;
        while(!(current.right == null)){
        	current = current.right;
        }
	return current.data;
  }
  
  ////////////////////////////////////////////////// ๐Ÿ’– ์ถ”๊ฐ€ ////////////////////////////////////////////////// 
    
}

// ์ถœ๋ ฅ ์œ ํ‹ธ ํ•จ์ˆ˜
function print(item){
		console.log(item);
}

// inorder traversal
function inOrder(node){
    if(!(node == null)){
        inOrder(node.left);
        print(node.show());
        inOrder(node.right);
    }
}
	// preOrder traversal
function preOrder(node){
    	if(!(node == null)){
        	print(node.show());
        	preOrder(node.left);
			preOrder(node.right);
        }
    }
    
	// postOrder traversal
function postOrder(node){
    	if(!(node == null)){
        	postOrder(node.left);
			postOrder(node.right);
            print(node.show());
        }
    }
  
let nums = new BST();
nums.insert(23);
nums.insert(45);
nums.insert(16);
nums.insert(37);
nums.insert(3);
nums.insert(99);
nums.insert(22);

let min = nums.getMin();
let max = nums.getMax();

print(`bst nums์˜ ์ตœ์†Œ๊ฐ’: ${min}, ์ตœ๋Œ€๊ฐ’: ${max}`);
// bst nums์˜ ์ตœ์†Œ๊ฐ’: 3, ์ตœ๋Œ€๊ฐ’: 99

ํŠน์ • ๊ฐ’ ์ฐพ๊ธฐ

bst์—์„œ ํŠน์ • ๊ฐ’์„ ์ฐพ๊ธฐ ์œ„ํ•ด์„œ๋Š” ํ˜„์žฌ ๋…ธ๋“œ์™€ ์ฐพ์œผ๋ ค๋Š” ๊ฐ’ ๊ฐ„์˜ ๋Œ€์†Œ ๋น„๊ต๊ฐ€ ํ•„์š”ํ•˜๋‹ค.

๋Œ€์†Œ ๋น„๊ต๋ฅผ ํ†ตํ•ด ์ฐพ์œผ๋ ค๋Š” ๊ฐ’์ด ํ˜„์žฌ ๋…ธ๋“œ๋ณด๋‹ค ํฌ๋‹ค๋ฉด ์˜ค๋ฅธ์ชฝ ๋…ธ๋“œ๋กœ ์ด๋™ํ•˜๊ณ ,

์ฐพ์œผ๋ ค๋Š” ๊ฐ’์ด ์ž‘๋‹ค๋ฉด ํ˜„์žฌ ๋…ธ๋“œ ๊ธฐ์ค€ ์™ผ์ชฝ ๋…ธ๋“œ๋กœ ์ด๋™ํ•ด์„œ ์ฐพ์œผ๋ฉด ๋œ๋‹ค.

 

find() ๋ฉ”์„œ๋“œ๋ฅผ ๊ตฌํ˜„ํ–ˆ๋˜ ํด๋ž˜์Šค์— ์ถ”๊ฐ€ํ•ด๋ณด์ž.

find(data){
	let current = this.root;
    while(current.data != data){
    	if(data < current.data){	// ์ฐพ์œผ๋ ค๋Š” ๊ฐ’์ด ํ˜„์žฌ ๋…ธ๋“œ๋ณด๋‹ค ์ž‘๋‹ค๋ฉด 
        	current = current.left;	// ์™ผ์ชฝ ์„œ๋ธŒ ํŠธ๋ฆฌ๋กœ ์ด๋™ํ•ด์„œ ๊ฒ€์ƒ‰
        } else {
        	current = current.right;	// ์˜ค๋ฅธ์ชฝ์œผ๋กœ ์ด๋™ํ•ด์„œ ๊ฒ€์ƒ‰
        }
        
        if(current == null){
        	return null;
        }
    }
    return current;
}

 

๐Ÿ‘‡ ์ „์ฒด ์ฝ”๋“œ!

๋”๋ณด๊ธฐ
class Node{
	constructor(data, left, right){
		this.data = data;
        this.left = left;
        this.right = right;
	}
    
    // ํ˜„์žฌ ๋…ธ๋“œ์˜ ๋ฐ์ดํ„ฐ ๋ณด์—ฌ์ฃผ๊ธฐ 
	show(){
    	return this.data;
    }
}

class BST{
	constructor(){
    	this.root = null;
    }
    
    // ๋…ธ๋“œ ์ถ”๊ฐ€
	insert(data){
    	let n = new Node(data,null,null); // ์ถ”๊ฐ€ํ•  ๋…ธ๋“œ ์ƒ์„ฑ
        if(this.root == null){ // ๋ฃจํŠธ๊ฐ€ ๋น„์–ด ์žˆ๋‹ค๋ฉด ์ถ”๊ฐ€ํ•  ๋…ธ๋“œ๋ฅผ ๋ฃจํŠธ ๋…ธ๋“œ๋กœ ํ• ๋‹น
        	this.root = n;
        } else {
        	let current = this.root; // ๋ฃจํŠธ๊ฐ€ ๋น„์–ด ์žˆ์ง€ ์•Š๋‹ค๋ฉด ํ˜„์žฌ ๋ฃจํŠธ๋ฅผ ๊ธฐ์ค€์œผ๋กœ
            let parent;
            while(true){
            	parent = current;	// ๋ถ€๋ชจ๋ฅผ ํ˜„์žฌ ๋ฃจํŠธ ๋…ธ๋“œ๋กœ ํ•˜๊ณ 
                if(data < current.data){	// ํ˜„์žฌ ๋ฐ์ดํ„ฐ๊ฐ€ ๋ถ€๋ชจ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์ž‘๋‹ค๋ฉด
                	current = current.left; 
                    if(current == null){
                    	parent.left = n; // ๋ถ€๋ชจ ๋…ธ๋“œ ๊ธฐ์ค€ ์™ผ์ชฝ์— ํ• ๋‹นํ•œ๋‹ค
                        break;
                    }
                } else {
                	current = current.right; // ํ˜„์žฌ ๋ฐ์ดํ„ฐ๊ฐ€ ๋ถ€๋ชจ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ํฌ๋‹ค๋ฉด
                    if(current == null){	
                    	parent.right = n; // ๋ถ€๋ชจ ๋…ธ๋“œ ๊ธฐ์ค€์œผ๋กœ ์˜ค๋ฅธ์ชฝ์œผ๋กœ ํ• ๋‹น
                        break;
                    }
                }
            }
        
        }
    
    }
	
    
    getMin(){
    	let current = this.root;			// ๋ฃจํŠธ ๋…ธ๋“œ๋กœ๋ถ€ํ„ฐ ์‹œ์ž‘ํ•ด์„œ 
            while(!(current.left == null)){		// ๋” ์ด์ƒ ์™ผ์ชฝ ์ž์‹ ๋…ธ๋“œ๊ฐ€ ์—†์„ ๋•Œ๊นŒ์ง€ ๊ฒ€์ƒ‰
            	current = current.left;
            }
        return current.data;		// ๋งจ ์™ผ์ชฝ์˜ leaf ๋…ธ๋“œ๊ฐ€ ๊ฐ€์žฅ ์ž‘์€ ๊ฐ’์ด๋ฏ€๋กœ ๋ฆฌํ„ด
    }


  getMax(){
	let current = this.root;
        while(!(current.right == null)){
        	current = current.right;
        }
	return current.data;
  }
  
  ////////////////////////////////////////////////// ๐Ÿ’– ์ถ”๊ฐ€ ////////////////////////////////////////////////// 
  
  find(data){
	let current = this.root;
    while(current.data != data){
    	if(data < current.data){	// ์ฐพ์œผ๋ ค๋Š” ๊ฐ’์ด ํ˜„์žฌ ๋…ธ๋“œ๋ณด๋‹ค ์ž‘๋‹ค๋ฉด 
        	current = current.left;	// ์™ผ์ชฝ ์„œ๋ธŒ ํŠธ๋ฆฌ๋กœ ์ด๋™ํ•ด์„œ ๊ฒ€์ƒ‰
        } else {
        	current = current.right;	// ์˜ค๋ฅธ์ชฝ์œผ๋กœ ์ด๋™ํ•ด์„œ ๊ฒ€์ƒ‰
        }
        
        if(current == null){
        	return null;
        }
    }
    return current;
}
  
  
  ////////////////////////////////////////////////// ๐Ÿ’– ์ถ”๊ฐ€ ////////////////////////////////////////////////// 
}

// ์ถœ๋ ฅ ์œ ํ‹ธ ํ•จ์ˆ˜
function print(item){
		console.log(item);
}

// inorder traversal
function inOrder(node){
    if(!(node == null)){
        inOrder(node.left);
        print(node.show());
        inOrder(node.right);
    }
}
	// preOrder traversal
function preOrder(node){
    	if(!(node == null)){
        	print(node.show());
        	preOrder(node.left);
			preOrder(node.right);
        }
    }
    
	// postOrder traversal
function postOrder(node){
    	if(!(node == null)){
        	postOrder(node.left);
			postOrder(node.right);
            print(node.show());
        }
    }
  
let nums = new BST();
nums.insert(23);
nums.insert(45);
nums.insert(16);
nums.insert(37);
nums.insert(3);
nums.insert(99);
nums.insert(22);

let findValues = [3,12,25,23,33,45,99];

findValues.forEach((value)=>{
    let hit = nums.find(value);
    print(`value ${value} ${hit==null?"is not":""} in bst`);
})
/**
value 3  in bst
value 12 is not in bst
value 25 is not in bst
value 23  in bst
value 33 is not in bst
value 45  in bst
value 99  in bst
*/



BST์—์„œ ๋…ธ๋“œ ์ œ๊ฑฐ

BST ์—ฐ์‚ฐ ์ค‘์—์„œ ๊ฐ€์žฅ ๋ณต์žกํ•œ ์—ฐ์‚ฐ์€ ๋…ธ๋“œ๋ฅผ ์ œ๊ฑฐํ•˜๋Š” ๊ณผ์ •์ด๋‹ค. ๋…ธ๋“œ ์ œ๊ฑฐ์˜ ๋ณต์žก๋„๋Š” ์–ด๋–ค ๋…ธ๋“œ๋ฅผ ์ œ๊ฑฐํ•˜๊ณ  ์‹ถ๋ƒ์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์ง„๋‹ค. leaf ๋…ธ๋“œ๋ฅผ ์ œ๊ฑฐํ•˜๊ณ  ์‹ถ์€ ๊ฒฝ์šฐ ์ œ๊ฑฐ ์ฝ”๋“œ๋ฅผ ๋น„๊ต์  ๊ฐ„๋‹จํ•˜๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.

ํ•˜์ง€๋งŒ ์ž์‹ ๋…ธ๋“œ๊ฐ€ ํ•˜๋‚˜ ์žˆ๋‹ค๋ฉด ์ข€ ๋” ๋ณต์žกํ•ด์ง€๊ณ , ์ž์‹ ๋…ธ๋“œ๊ฐ€ ๋‘˜์ด๋ผ๋ฉด ๋”์šฑ ๋” ๋ณต์žกํ•ด์ง„๋‹ค.

 

๋…ธ๋“œ ์‚ญ์ œ์˜ ๋ณต์žก๋„๋ฅผ ๋‚ฎ์ถ”๊ธฐ ์œ„ํ•ด ๋…ธ๋“œ๋ฅผ ์žฌ๊ท€์ ์œผ๋กœ ์ œ๊ฑฐํ•˜๋Š” ๊ณผ์ •์œผ๋กœ ๊ฐ„์†Œํ™”ํ•ด๋ณด๊ณ ์ž ํ•œ๋‹ค.

๋…ธ๋“œ๋ฅผ ์ œ๊ฑฐํ•˜๊ธฐ ์œ„ํ•œ ๋ฉ”์„œ๋“œ๋Š” ๋‘๊ฐ€์ง€๋‹ค : remove()์™€ removeNode()

๊ตฌํ˜„ ๋…ผ๋ฆฌ

1. ํ˜„์žฌ ๋…ธ๋“œ๊ฐ€ ์šฐ๋ฆฌ๊ฐ€ ์‚ญ์ œํ•˜๋ ค๋Š” ๋…ธ๋“œ๋ฅผ ํฌํ•จํ•˜๊ณ  ์žˆ๋Š”๊ฐ€? => ํ•ด๋‹น ๋…ธ๋“œ ์‚ญ์ œ

2. ์•„๋‹ˆ๋ผ๋ฉด ํ˜„์žฌ๋…ธ๋“œ์™€ ์šฐ๋ฆฌ๊ฐ€ ์‚ญ์ œํ•˜๋ ค๋Š” ๋…ธ๋“œ ๋น„๊ต

    2 - 1. ์‚ญ์ œํ•˜๊ณ ์žํ•˜๋Š” ๋…ธ๋“œ๊ฐ€ ํ˜„์žฌ ๋…ธ๋“œ๋ณด๋‹ค ์ž‘๋‹ค๋ฉด ์™ผ์ชฝ ์ž์‹ ๋…ธ๋“œ๋กœ ์ด๋™ํ•ด์„œ ๋น„๊ต

    2 - 2. ์‚ญ์ œํ•˜๊ณ ์žํ•˜๋Š” ๋ฐ์ดํ„ฐ๊ฐ€ ํ˜„์žฌ ๋…ธ๋“œ๋ณด๋‹ค ํฌ๋‹ค๋ฉด ์˜ค๋ฅธ์ชฝ ์ž์‹ ๋…ธ๋“œ๋กœ ์ด๋™ํ•ด์„œ ๋น„๊ต

 

๊ณ ๋ ค์‚ฌํ•ญ

 

1. ์ œ๊ฑฐํ•˜๋ ค๋Š” ๋…ธ๋“œ๊ฐ€ leaf์ธ ๊ฒฝ์šฐ => ํ•ด๋‹น ๋…ธ๋“œ์˜ parent node๊ฐ€ null์„ ๊ฐ€๋ฆฌํ‚ค๋„๋ก 

2. ์ œ๊ฑฐํ•˜๋ ค๋Š” ๋…ธ๋“œ๊ฐ€ ํ•˜๋‚˜์˜ ์ž์‹ ๋…ธ๋“œ๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ => ์ž์‹ ๋…ธ๋“œ๊ฐ€ ์ œ๊ฑฐํ•˜๋ ค๋Š” ๋…ธ๋“œ์˜ ๋ถ€๋ชจ ๋…ธ๋“œ๋ฅผ ๊ฐ€๋ฅดํ‚ค๋„๋ก 

3. ์ œ๊ฑฐํ•˜๋ ค๋Š” ๋…ธ๋“œ๊ฐ€ ๋‘ ๊ฐœ์˜ ์ž์‹ ๋…ธ๋“œ๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ

    3 - 1. ์ œ๊ฑฐํ•œ ๋…ธ๋“œ์˜ ์™ผ์ชฝ์—์„œ subtree ์ค‘ ๊ฐ€์žฅ ํฐ ๊ฐ’์„ ์ฐพ๊ฑฐ๋‚˜

    3 - 2. ์ œ๊ฑฐํ•œ ๋…ธ๋“œ์˜ ์˜ค๋ฅธ์ชฝ์—์„œ subtree ์ค‘ ๊ฐ€์žฅ ์ž‘์€ ๊ฐ’์„ ์ฐพ๊ธฐ ( โ˜‘๏ธ ์„ ํƒ )

 

4. subtree์˜ ์ตœ์†Œ๊ฐ’์„ ๊ตฌํ•˜๋Š” ํ•จ์ˆ˜ => ์ž„์‹œ ์ตœ์†Œ ๊ฐ’์„ ์ง€๋‹Œ ๋…ธ๋“œ ๊ตฌํ•ด์„œ ํ˜„์žฌ

 

์ž์‹ ๋…ธ๋“œ๊ฐ€ ๋‘๊ฐœ์ธ ๋…ธ๋“œ ์‚ญ์ œ ๊ณผ์ •

๋”๋ณด๊ธฐ
class Node{
	constructor(data, left, right){
		this.data = data;
        this.left = left;
        this.right = right;
	}
    
    // ํ˜„์žฌ ๋…ธ๋“œ์˜ ๋ฐ์ดํ„ฐ ๋ณด์—ฌ์ฃผ๊ธฐ 
	show(){
    	return this.data;
    }
}

class BST{
	constructor(){
    	this.root = null;
    }
    
    // ๋…ธ๋“œ ์ถ”๊ฐ€
	insert(data){
    	let n = new Node(data,null,null); // ์ถ”๊ฐ€ํ•  ๋…ธ๋“œ ์ƒ์„ฑ
        if(this.root == null){ // ๋ฃจํŠธ๊ฐ€ ๋น„์–ด ์žˆ๋‹ค๋ฉด ์ถ”๊ฐ€ํ•  ๋…ธ๋“œ๋ฅผ ๋ฃจํŠธ ๋…ธ๋“œ๋กœ ํ• ๋‹น
        	this.root = n;
        } else {
        	let current = this.root; // ๋ฃจํŠธ๊ฐ€ ๋น„์–ด ์žˆ์ง€ ์•Š๋‹ค๋ฉด ํ˜„์žฌ ๋ฃจํŠธ๋ฅผ ๊ธฐ์ค€์œผ๋กœ
            let parent;
            while(true){
            	parent = current;	// ๋ถ€๋ชจ๋ฅผ ํ˜„์žฌ ๋ฃจํŠธ ๋…ธ๋“œ๋กœ ํ•˜๊ณ 
                if(data < current.data){	// ํ˜„์žฌ ๋ฐ์ดํ„ฐ๊ฐ€ ๋ถ€๋ชจ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์ž‘๋‹ค๋ฉด
                	current = current.left; 
                    if(current == null){
                    	parent.left = n; // ๋ถ€๋ชจ ๋…ธ๋“œ ๊ธฐ์ค€ ์™ผ์ชฝ์— ํ• ๋‹นํ•œ๋‹ค
                        break;
                    }
                } else {
                	current = current.right; // ํ˜„์žฌ ๋ฐ์ดํ„ฐ๊ฐ€ ๋ถ€๋ชจ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ํฌ๋‹ค๋ฉด
                    if(current == null){	
                    	parent.right = n; // ๋ถ€๋ชจ ๋…ธ๋“œ ๊ธฐ์ค€์œผ๋กœ ์˜ค๋ฅธ์ชฝ์œผ๋กœ ํ• ๋‹น
                        break;
                    }
                }
            }
        
        }
    
    }
	
    
    getMin(){
    	let current = this.root;			// ๋ฃจํŠธ ๋…ธ๋“œ๋กœ๋ถ€ํ„ฐ ์‹œ์ž‘ํ•ด์„œ 
            while(!(current.left == null)){		// ๋” ์ด์ƒ ์™ผ์ชฝ ์ž์‹ ๋…ธ๋“œ๊ฐ€ ์—†์„ ๋•Œ๊นŒ์ง€ ๊ฒ€์ƒ‰
            	current = current.left;
            }
        return current.data;		// ๋งจ ์™ผ์ชฝ์˜ leaf ๋…ธ๋“œ๊ฐ€ ๊ฐ€์žฅ ์ž‘์€ ๊ฐ’์ด๋ฏ€๋กœ ๋ฆฌํ„ด
    }


  getMax(){
	let current = this.root;
        while(!(current.right == null)){
        	current = current.right;
        }
	return current.data;
  }

      
  find(data){
	let current = this.root;
    while(current.data != data){
    	if(data < current.data){	// ์ฐพ์œผ๋ ค๋Š” ๊ฐ’์ด ํ˜„์žฌ ๋…ธ๋“œ๋ณด๋‹ค ์ž‘๋‹ค๋ฉด 
        	current = current.left;	// ์™ผ์ชฝ ์„œ๋ธŒ ํŠธ๋ฆฌ๋กœ ์ด๋™ํ•ด์„œ ๊ฒ€์ƒ‰
        } else {
        	current = current.right;	// ์˜ค๋ฅธ์ชฝ์œผ๋กœ ์ด๋™ํ•ด์„œ ๊ฒ€์ƒ‰
        }
        
        if(current == null){
        	return null;
        }
    }
    return current;
}
  
  
  ////////////////////////////////////////////////// ๐Ÿ’– ์ถ”๊ฐ€ ////////////////////////////////////////////////// 
    remove(data){
        this.root = this.removeNode(this.root, data);
    }

    removeNode(node, data){
        if(node == null){
            return null;
        }
        if(data == node.data){
            // ๋…ธ๋“œ๊ฐ€ ์ž์‹์ด ์—†์„ ๊ฒฝ์šฐ
            if(node.left == null && node.right == null){
                return null;
            }
            // ๋…ธ๋“œ๊ฐ€ ์™ผ์ชฝ ์ž์‹์ด ์—†์„ ๊ฒฝ์šฐ
            if(node.left == null){
                return node.right;
            }
           // ๋…ธ๋“œ๊ฐ€ ์˜ค๋ฅธ์ชฝ ์ž์‹์ด ์—†์„ ๊ฒฝ์šฐ
            if(node.right == null){
                return node.left;
            }
            // ๋…ธ๋“œ๊ฐ€ ์ž์‹์ด ๋‘๊ฐœ์•ˆ ๊ฒฝ์šฐ
            let tempNode = this.getMin();
            node.data = tempNode.data;
            node.right = this.removeNode(node.right, tempNode.data);
            return node;
        }
        else if(data< node.data){
            node.left = this.removeNode(node.left, data);
            return node;
        } else {
            node.right = this.removeNode(node.right,data);
            return node;
        }
        
    }
  
  ////////////////////////////////////////////////// ๐Ÿ’– ์ถ”๊ฐ€ ////////////////////////////////////////////////// 
}

// ์ถœ๋ ฅ ์œ ํ‹ธ ํ•จ์ˆ˜
function print(item){
		console.log(item);
}

// inorder traversal
function inOrder(node){
    if(!(node == null)){
        inOrder(node.left);
        print(node.show());
        inOrder(node.right);
    }
}
	// preOrder traversal
function preOrder(node){
    	if(!(node == null)){
        	print(node.show());
        	preOrder(node.left);
			preOrder(node.right);
        }
    }
    
	// postOrder traversal
function postOrder(node){
    	if(!(node == null)){
        	postOrder(node.left);
			postOrder(node.right);
            print(node.show());
        }
    }
  
let nums = new BST();
nums.insert(23);
nums.insert(45);
nums.insert(16);
nums.insert(37);
nums.insert(3);
nums.insert(99);
nums.insert(22);

// let findValues = [3,12,25,23,33,45,99];
// findValues.forEach((value)=>{
//     let hit = nums.find(value);
//     print(`value ${value} ${hit==null?"is not":""} in bst`);
// })
nums.remove(23);
inOrder(nums.root);

/**
3
16
22
undefined
37
45
99

*/
// ๋งจ ์™ผ์ชฝ์˜ ๋ฆฌํ”„ ์ œ๊ฑฐ
nums.remove(3);
inOrder(nums.root);
/**
16
22
23
37
45
99
*/
// ๋งจ ์˜ค๋ฅธ์ชฝ์˜ ๋ฆฌํ”„ ์ œ๊ฑฐ
nums.remove(99);
inOrder(nums.root);
/**
3
16
22
23
37
45
*/
nums.insert(23);
nums.insert(45);
nums.insert(16);
nums.insert(37);
nums.insert(3);
nums.insert(99);
nums.insert(22);

nums.remove(37);

// ์˜ค๋ฅธ์ชฝ ์ž์‹์ด ํ•˜๋‚˜์ธ ๋…ธ๋“œ ์ œ๊ฑฐ
nums.remove(45);
inOrder(nums.root);

/**
3
16
22
23
99
*/
let nums = new BST();
nums.insert(23);
nums.insert(45);
nums.insert(16);
nums.insert(37);
nums.insert(3);
nums.insert(99);
nums.insert(22);

nums.remove(3);
inOrder(nums.root);
print('์™ผ์ชฝ ์ž์‹์ด ํ•˜๋‚˜์ธ ๋…ธ๋“œ ์ œ๊ฑฐ')
// ์™ผ์ชฝ ์ž์‹์ด ํ•˜๋‚˜์ธ ๋…ธ๋“œ ์ œ๊ฑฐ
nums.remove(16);
inOrder(nums.root);
/**
16
22
23
37
45
99
VM540:127 ์™ผ์ชฝ ์ž์‹์ด ํ•˜๋‚˜์ธ ๋…ธ๋“œ ์ œ๊ฑฐ
22
23
37
45
99
*/
nums.insert(23);
nums.insert(45);
nums.insert(16);
nums.insert(37);
nums.insert(3);
nums.insert(99);
nums.insert(22);

// ์ž์‹ ๋…ธ๋“œ๊ฐ€ ๋‘ ๊ฐœ์ธ ๋…ธ๋“œ ์ œ๊ฑฐ 
nums.remove(16);
inOrder(nums.root);

/**
3
undefined
22
23
37
45
99
*/

๋นˆ๋„์ˆ˜ ์นด์šดํŠธ

์–ด๋–ค ์ˆซ์ž๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๋นˆ๋„์ˆ˜๋ฅผ ์ฒดํฌํ•  ๋•Œ bst๋ฅผ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.์˜ˆ๋ฅผ ๋“ค๋ฉด ํ•™์ƒ๋“ค ์„ฑ์  ๋ถ„ํฌ๋ฅผ bst๋กœ ๋‚˜ํƒ€๋‚ผ ์ˆ˜ ์žˆ๋Š”๋ฐ, ์ ์ˆ˜๊ฐ€ bst์— ์—†๋‹ค๋ฉด ์ถ”๊ฐ€ํ•ด์ฃผ๊ณ , ์žˆ๋‹ค๋ฉด ํ•ด๋‹น ๋…ธ๋“œ์˜ ๋นˆ๋„์ˆ˜++์„ ํ•ด์ฃผ๋ฉด ๋œ๋‹ค.

 

๊ทธ๋Ÿฌ๊ธฐ ์œ„ํ•ด์„œ๋Š” Node ํด๋ž˜์Šค๊ฐ€ ๋นˆ๋„์ˆ˜ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ–๋„๋ก ์‚ด์ง ๋ณ€๊ฒฝ์„ ํ•ด์ค˜์•ผ ํ•œ๋‹ค.

class Node{
	constructor(data,left,right){
    	this.data = data;
        this count = 1;	/** ๐Ÿ’– ์ถ”๊ฐ€ */
        this.left = left;
        this.right = right;
    }
	show(){
    	return this.data;
    }
}

 

์„ฑ์  ๋…ธ๋“œ๊ฐ€ BST์— ์ถ”๊ฐ€๋˜๋ฉด ๋นˆ๋„์ˆ˜ ์นด์šดํŠธ๋Š” 1๋กœ ์ดˆ๊ธฐํ™”๋œ๋‹ค.

BST ๋…ธ๋“œ insert์‹œ ๋นˆ๋„์ˆ˜๋„ ์ฆ๊ฐ€ํ•˜๋„๋ก update ๋ฉ”์„œ๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ด์ฃผ์ž.

// ๋…ธ๋“œ ์ถ”๊ฐ€ ์‹œ ๋นˆ๋„์ˆ˜ ++
update(data){
	let grade = this.find(data);
    grade.count ++;
    return grade;
}

 

๐Ÿ‘‡ ์ „์ฒด ์ฝ”๋“œ!

class Node{
	constructor(data, left, right){
		this.data = data;
        this.left = left;
        this.right = right;
        this.count = 1;
	}
    ////////////////////////////////////////////////// ๐Ÿ’– ์ถ”๊ฐ€ ////////////////////////////////////////////////// 
    // ํ˜„์žฌ ๋…ธ๋“œ์˜ ๋ฐ์ดํ„ฐ ๋ณด์—ฌ์ฃผ๊ธฐ 
	show(){
    	return [`${this.data}์ `, this.count];
    }
    ////////////////////////////////////////////////// ๐Ÿ’– ์ถ”๊ฐ€ ////////////////////////////////////////////////// 
}

class BST{
	constructor(){
    	this.root = null;
    }
    
    // ๋…ธ๋“œ ์ถ”๊ฐ€
	insert(data){
    	let n = new Node(data,null,null); // ์ถ”๊ฐ€ํ•  ๋…ธ๋“œ ์ƒ์„ฑ
        if(this.root == null){ // ๋ฃจํŠธ๊ฐ€ ๋น„์–ด ์žˆ๋‹ค๋ฉด ์ถ”๊ฐ€ํ•  ๋…ธ๋“œ๋ฅผ ๋ฃจํŠธ ๋…ธ๋“œ๋กœ ํ• ๋‹น
        	this.root = n;
        } else {
        	let current = this.root; // ๋ฃจํŠธ๊ฐ€ ๋น„์–ด ์žˆ์ง€ ์•Š๋‹ค๋ฉด ํ˜„์žฌ ๋ฃจํŠธ๋ฅผ ๊ธฐ์ค€์œผ๋กœ
            let parent;
            while(true){
            	parent = current;	// ๋ถ€๋ชจ๋ฅผ ํ˜„์žฌ ๋ฃจํŠธ ๋…ธ๋“œ๋กœ ํ•˜๊ณ 
                if(data < current.data){	// ํ˜„์žฌ ๋ฐ์ดํ„ฐ๊ฐ€ ๋ถ€๋ชจ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์ž‘๋‹ค๋ฉด
                	current = current.left; 
                    if(current == null){
                    	parent.left = n; // ๋ถ€๋ชจ ๋…ธ๋“œ ๊ธฐ์ค€ ์™ผ์ชฝ์— ํ• ๋‹นํ•œ๋‹ค
                        break;
                    }
                } else {
                	current = current.right; // ํ˜„์žฌ ๋ฐ์ดํ„ฐ๊ฐ€ ๋ถ€๋ชจ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ํฌ๋‹ค๋ฉด
                    if(current == null){	
                    	parent.right = n; // ๋ถ€๋ชจ ๋…ธ๋“œ ๊ธฐ์ค€์œผ๋กœ ์˜ค๋ฅธ์ชฝ์œผ๋กœ ํ• ๋‹น
                        break;
                    }
                }
            }
        
        }
    
    }
	
    
    getMin(){
    	let current = this.root;			// ๋ฃจํŠธ ๋…ธ๋“œ๋กœ๋ถ€ํ„ฐ ์‹œ์ž‘ํ•ด์„œ 
            while(!(current.left == null)){		// ๋” ์ด์ƒ ์™ผ์ชฝ ์ž์‹ ๋…ธ๋“œ๊ฐ€ ์—†์„ ๋•Œ๊นŒ์ง€ ๊ฒ€์ƒ‰
            	current = current.left;
            }
        return current.data;		// ๋งจ ์™ผ์ชฝ์˜ leaf ๋…ธ๋“œ๊ฐ€ ๊ฐ€์žฅ ์ž‘์€ ๊ฐ’์ด๋ฏ€๋กœ ๋ฆฌํ„ด
    }


  getMax(){
	let current = this.root;
        while(!(current.right == null)){
        	current = current.right;
        }
	return current.data;
  }

      
  find(data){
	let current = this?.root;
    if(current?.data == null) return null;
    while(current.data != data){
    	if(data < current.data){	// ์ฐพ์œผ๋ ค๋Š” ๊ฐ’์ด ํ˜„์žฌ ๋…ธ๋“œ๋ณด๋‹ค ์ž‘๋‹ค๋ฉด 
        	current = current.left;	// ์™ผ์ชฝ ์„œ๋ธŒ ํŠธ๋ฆฌ๋กœ ์ด๋™ํ•ด์„œ ๊ฒ€์ƒ‰
        } else {
        	current = current.right;	// ์˜ค๋ฅธ์ชฝ์œผ๋กœ ์ด๋™ํ•ด์„œ ๊ฒ€์ƒ‰
        }
        
        if(current == null){
        	return null;
        }
    }
    return current;
}
  
    remove(data){
        this.root = this.removeNode(this.root, data);
    }

    removeNode(node, data){
        if(node == null){
            return null;
        }
        if(data == node.data){
            // ๋…ธ๋“œ๊ฐ€ ์ž์‹์ด ์—†์„ ๊ฒฝ์šฐ
            if(node.left == null && node.right == null){
                return null;
            }
            // ๋…ธ๋“œ๊ฐ€ ์™ผ์ชฝ ์ž์‹์ด ์—†์„ ๊ฒฝ์šฐ
            if(node.left == null){
                return node.right;
            }
           // ๋…ธ๋“œ๊ฐ€ ์˜ค๋ฅธ์ชฝ ์ž์‹์ด ์—†์„ ๊ฒฝ์šฐ
            if(node.right == null){
                return node.left;
            }
            // ๋…ธ๋“œ๊ฐ€ ์ž์‹์ด ๋‘๊ฐœ์•ˆ ๊ฒฝ์šฐ
            let tempNode = this.getMin();
            node.data = tempNode.data;
            node.right = this.removeNode(node.right, tempNode.data);
            return node;
        }
        else if(data< node.data){
            node.left = this.removeNode(node.left, data);
            return node;
        } else {
            node.right = this.removeNode(node.right,data);
            return node;
        }
        
    }
  
  ////////////////////////////////////////////////// ๐Ÿ’– ์ถ”๊ฐ€ ////////////////////////////////////////////////// 

// ๋…ธ๋“œ ์ถ”๊ฐ€ ์‹œ ๋นˆ๋„์ˆ˜ ++
update(data){
	let grade = this.find(data);
    grade.count ++;
    return grade;
}
  ////////////////////////////////////////////////// ๐Ÿ’– ์ถ”๊ฐ€ ////////////////////////////////////////////////// 
    
}

const arr =[];

////////////////////////////////////////////////// ๐Ÿ’– ์ถ”๊ฐ€ ////////////////////////////////////////////////// 

// ์ถœ๋ ฅ ์œ ํ‹ธ ํ•จ์ˆ˜, ๋‘๋ฒˆ์งธ ์ธ์ž๋ฅผ true๋กœ ๋„˜๊ธฐ๋ฉด table ํ˜•์‹์œผ๋กœ ์ถœ๋ ฅ
function print(item,table=false){
		!table?console.log(item):console.table(item);
}
////////////////////////////////////////////////// ๐Ÿ’– ์ถ”๊ฐ€ ////////////////////////////////////////////////// 

// inorder traversal
function inOrder(node){
    if(!(node == null)){
        inOrder(node.left);
        arr.push(node.show());
        // print(node.show());
        inOrder(node.right);
    }
}
// preOrder traversal
function preOrder(node){
    	if(!(node == null)){
        	print(node.show());
        	preOrder(node.left);
			preOrder(node.right);
        }
    }
    
	// postOrder traversal
function postOrder(node){
    	if(!(node == null)){
        	postOrder(node.left);
			postOrder(node.right);
            print(node.show());
        }
    }
  

////////////////////////////////////////////////// ๐Ÿ’– ์ถ”๊ฐ€ ////////////////////////////////////////////////// 

let grades = new BST();
const scores = Array.from({length: 100},()=>Math.floor(Math.random()*101));
scores.forEach((score)=>{
    let scoreExists = grades.find(score);
    if(scoreExists == null){
        grades.insert(score);
    } else {
        grades.update(score);
    }
});
inOrder(grades.root);

print(arr,true);

////////////////////////////////////////////////// ๐Ÿ’– ์ถ”๊ฐ€ //////////////////////////////////////////////////

 

์ถœ๋ ฅ ๊ฒฐ๊ณผ

๐Ÿ€ ๋งˆ์น˜๋ฉด์„œ

TMI...traversal gif ์‚ฝ์ž… ์ค‘ ์—๋Ÿฌ ๋ฐœ์ƒ ใ…œใ…œ ์ด๋ฏธ ๊ธ€์„ ๋“ฑ๋กํ•œ ์ƒํƒœ๋ผ์„œ ์ž๋™ ์ €์žฅ์ด ์•ˆ๋ผ์„œ bst ํƒ์ƒ‰ ์ด์ „๋ถ€ํ„ฐ  ๊ธ€์„ ๋‘๋ฒˆ ์“ฐ๋Š” ์ค‘ ใ…œใ…œใ…œใ…œ 
bst์— ๋Œ€ํ•ด์„œ๋Š” ํ™•์‹คํžˆ ์•Œ๊ณ  ๊ฐ€๋Š” ์‹œ๊ฐ„์ด ๋œ ๊ฑฐ ๊ฐ™๋‹ค ๐Ÿ˜‚๐Ÿ˜‚๐Ÿ˜‚๐Ÿ˜‚๐Ÿ˜‚๐Ÿ˜‚

๐Ÿ“š Reference

- Data Structures and Algorithms Using Javaโ€ Script by Michael McMillian (O’Reilly). Copyright 2014 Michael McMillan, 978-1-449-36493-9