๐Ÿ“Š ํŠธ๋ผ์ด๋ฅผ ์ด์šฉํ•œ ์ž๋™์™„์„ฑ ๊ธฐ๋Šฅ ๊ตฌํ˜„

๋ฐ•๋ฏผ์šฐยท2023๋…„ 6์›” 11์ผ
1
post-thumbnail

ํ”„๋กœ๊ทธ๋ž˜๋จธ์Šค ํ”„๋ก ํŠธ์—”๋“œ ๋ฐ๋ธŒ์ฝ”์Šค 2์ฃผ์ฐจ ๊ณผ์ œ์ธ ํŠธ๋ผ์ด ์ž๋ฃŒ๊ตฌ์กฐ๋ฅผ ์ด์šฉํ•œ ์ž๋™์™„์„ฑ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•ด๋ณด์•˜๋‹ค.

๐Ÿ’ก ์ž๋™์™„์„ฑ ๊ธฐ๋Šฅ์ด๋ž€ ?

=> ์‚ฌ์šฉ์ž๊ฐ€ ์ž…๋ ฅํ•œ ๊ฒ€์ƒ‰์–ด๋กœ๋ถ€ํ„ฐ ์ถ”์ฒœ๋œ ๊ฒ€์ƒ‰์–ด ๋ฆฌ์ŠคํŠธ๋ฅผ ๋ณด์—ฌ์ฃผ๋Š” ๊ฒƒ

์ž๋™์™„์„ฑ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜๊ธฐ ์ „, ์šฐ์„  ํŠธ๋ผ์ด ์ž๋ฃŒ๊ตฌ์กฐ์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ณด์ž.


๐Ÿ“Œ ํŠธ๋ผ์ด

ํŠธ๋ผ์ด๋ž€ ?

๋ฌธ์ž์—ด์„ ์ €์žฅํ•˜๊ณ  ํšจ์œจ์ ์œผ๋กœ ํƒ์ƒ‰ํ•˜๊ธฐ ์œ„ํ•œ ํŠธ๋ฆฌ ํ˜•ํƒœ์˜ ์ž๋ฃŒ ๊ตฌ์กฐ์ด๋‹ค.


JS์—์„œ ํŠธ๋ผ์ด์˜ ๊ตฌํ˜„

=> ํŠธ๋ฆฌ ๊ตฌ์กฐ๋ฅผ ๊ตฌ์„ฑํ•˜๋Š” ๋…ธ๋“œ๋“ค์„ ์ธ์ ‘ ๋ฆฌ์ŠคํŠธ ํ˜•ํƒœ๋กœ ๊ตฌํ˜„

class Node{
    constructor(value=""){
        this.value = value; // ๋…ธ๋“œ์— ๋“ค์–ด๊ฐˆ ๋ฌธ์ž ๊ฐ’ 
        this.children = new Map();  // ์—ฐ๊ฒฐ๋œ ๋‹ค์Œ ๋…ธ๋“œ๋“ค์˜ ๋ฌธ์ž๊ฐ’ ?    
        // 
    }
}
  • ๋ฃจํŠธ ๋…ธ๋“œ์˜ value๋Š” ""์ด๊ณ , children์ด๋ผ๋Š” map ์ž๋ฃŒ๊ตฌ์กฐ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๊ณ , ์ด children์˜ ๊ฐ entry๋“ค์˜ key ๊ฐ’์€ ๊ฐ„์„ ์„ ์˜๋ฏธํ•˜๊ณ , value ๊ฐ’์ด ์—ฐ๊ฒฐ๋œ ๋…ธ๋“œ๋ฅผ ์˜๋ฏธํ•œ๋‹ค.

    => ์œ„ ์˜ˆ์‹œ ๊ทธ๋ฆผ์—์„œ t ๋…ธ๋“œ์˜ value๋Š” t์ด๊ณ , children์€ map ์ž๋ฃŒ๊ตฌ์กฐ๋กœ 2๊ฐœ์˜ entry๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์œผ๋ฉฐ, ์ด๋Š”

    {"e" : value=te์ธ node}

    {"o" : value=to์ธ node } ์ด๋‹ค.


์ž์„ธํ•œ ๊ตฌํ˜„ ๋‚ด์šฉ์€ ๋‹ค์Œ ๋ชฉ์ฐจ์—์„œ ์‚ดํŽด๋ณด์ž !


๐Ÿ“Œ ํŠธ๋ผ์ด๋ฅผ ์ด์šฉํ•œ ์ž๋™์™„์„ฑ ๊ธฐ๋Šฅ ๊ตฌํ˜„

๋‚ด๊ฐ€ ์ด๋ฒˆ์— ๊ตฌํ˜„ํ•˜๊ณ ์ž ํ•˜๋Š” ์ž๋™์™„์„ฑ์˜ ๊ธฐ๋Šฅ์€ ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

์‚ฌ์šฉ์ž๊ฐ€ ์ž…๋ ฅํ•œ ๊ฒ€์ƒ‰์–ด๋กœ๋ถ€ํ„ฐ ์‹œ์ž‘๋  ์ˆ˜ ์žˆ๋Š” ๋‹ค๋ฅธ ๊ฒ€์ƒ‰์–ด๋“ค์˜ ๋ชฉ๋ก์„ ๊ฒ€์ƒ‰์–ด์˜ ๊ธธ์ด ์ˆœ์œผ๋กœ ๋ณด์—ฌ์ค€๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, plz, proud, program, picnic, programmers ์˜ ๊ฒ€์ƒ‰์–ด๋“ค์ด ๋“ฑ๋ก๋˜์–ด ์žˆ๊ณ  ์‚ฌ์šฉ์ž๊ฐ€ pro๋ฅผ ์ž…๋ ฅํ•œ๋‹ค๋ฉด => proud, program, programmers์˜ ๋‹จ์–ด๋“ค์„ ๋ณด์—ฌ์ฃผ๋Š” ๊ฒƒ์ด๋‹ค.

์ด๋Ÿฌํ•œ ๊ธฐ๋Šฅ์„ ํŠธ๋ผ์ด๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ๊ตฌํ˜„ํ•œ ๊ณผ์ •์„ ์•Œ์•„๋ณด์ž.


1. ํŠธ๋ผ์ด ๊ตฌํ˜„์„ ์œ„ํ•œ Queue, Node ํด๋ž˜์Šค ๊ตฌํ˜„

class Queue { // level order traversal์„ ์œ„ํ•œ Queue ๊ตฌํ˜„ 
    constructor(){
        this.queue = [];
        this.front = 0;
        this.back = 0;
    }

    enqueue(value){ 
        this.queue[this.back++] = value;
    }

    dequeue(){   
        const value = this.queue[this.front];
        delete this.queue[this.front]; // 
        this.front += 1;
        return value;
    }

    size(){
        return this.back - this.front;
    }
}

class Node {
    constructor(value="", isWord=false){
        this.value = value;
        this.children = new Map();
        this.isWord = isWord; // node์˜ value๊ฐ’์ด ๋“ฑ๋ก๋œ ๋‹จ์–ด์ธ์ง€ 
    }
}

Array๋ฅผ ์ด์šฉํ•ด Queue๋ฅผ ๊ตฌํ˜„ํ•˜๊ณ , ํŠธ๋ผ์ด๋ฅผ ๊ตฌ์„ฑํ•˜๋Š” ๋…ธ๋“œ์— ํ•ด๋‹นํ•˜๋Š” Node ํด๋ž˜์Šค๋„ ๊ตฌํ˜„ํ•ด์ฃผ์—ˆ๋‹ค.

Node ํด๋ž˜์Šค๋ฅผ ๊ตฌํ˜„ํ•  ๋•Œ, node์˜ ๊ฐ’์„ ๋‚˜ํƒ€๋‚ด๋Š” value ํ”„๋กœํผํ‹ฐ์™€ ์ž์‹ node์˜ ์ง‘ํ•ฉ์ธ children ํ”„๋กœํผํ‹ฐ ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ, ํ•ด๋‹น node์˜ value๊ฐ€ ๋“ฑ๋ก๋œ ๋‹จ์–ด์ธ์ง€๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” isWord ํ”„๋กœํผํ‹ฐ๋„ ํ•จ๊ป˜ ์„ ์–ธํ•ด์ฃผ์—ˆ๋‹ค.

isWord ํ”„๋กœํผํ‹ฐ๋ฅผ ์„ ์–ธํ•ด์ค€ ์ด์œ ๋Š” ?

์œ„์™€ ๊ฐ™์€ ํŠธ๋ผ์ด ๊ตฌ์กฐ์—์„œ ์œ ์ €๊ฐ€ ๋งŒ์•ฝ t๋ฅผ ์ž…๋ ฅํ–ˆ๋‹ค๋ฉด ?

t์˜ ์ž์‹ ๋…ธ๋“œ๋“ค์€ to, te, tea, ted, ten์ด ์žˆ์ง€๋งŒ์ด ์ค‘์—์„œ ์‹ค์ œ ๋‹จ์–ด์ธ tea, ted, ten, to ๋งŒ ์ถœ๋ ฅํ•˜๊ณ , te๋Š” ๋‹จ์–ด๋ฅผ ์ž…๋ ฅํ•˜๋Š” ๊ณผ์ •์—์„œ ํŠธ๋ผ์ด์— ์ถ”๊ฐ€๋˜๊ธด ํ–ˆ์ง€๋งŒ, ํŠน์ • ๋‹จ์–ด์˜ ์ผ๋ถ€๋ถ„์ด๊ธฐ ๋•Œ๋ฌธ์— ์ถœ๋ ฅํ•˜์ง€ ์•Š์œผ๋ ค๊ณ  ํ•œ๋‹ค.

๋”ฐ๋ผ์„œ, ๋‹จ์–ด๋“ค์„ ๋“ฑ๋กํ•  ๋•Œ isWord๋ฅผ true๋กœ ์„ค์ •ํ•ด์ฃผ๊ณ  isWord๊ฐ€ true์ธ ๋‹จ์–ด๋“ค๋งŒ ์ถœ๋ ฅํ•ด์ฃผ๋ ค๊ณ  ํ•œ๋‹ค.


2. ํŠธ๋ผ์ด ๊ตฌํ˜„ => insert, find ๋ฉ”์„œ๋“œ

class Trie {
    constructor(value=""){
        this.root = new Node(value);
    }

    insert(string){
        let currentNode = this.root;

        for(const char of string){
            if(!currentNode.children.has(char)){
                const charForInsert = currentNode.value + char; // ๋‹ค์Œ node์— ์ž…๋ ฅ๋  value๊ฐ’
                currentNode.children.set(
                    char,
                    new Node(charForInsert, charForInsert === string)
                );
            }

            currentNode = currentNode.children.get(char);
        }
    }
    
    find(string){ // string์— ํ•ด๋‹นํ•˜๋Š” node๋ฅผ ๋ฐ˜ํ™˜
        let currentNode = this.root;

        for(const char of string){
            if(!currentNode.children.has(char)){
                return null;
            }
            currentNode = currentNode.children.get(char);
        }
        return currentNode;
    }
}

insert ๋ฉ”์„œ๋“œ

์‚ฌ์šฉ์ž์—๊ฒŒ ๊ฒ€์ƒ‰์–ด๋ฅผ ์ถ”์ฒœํ•ด์ฃผ๊ธฐ ์œ„ํ•œ ๋ฆฌ์ŠคํŠธ์— ์ƒˆ๋กœ์šด ๋‹จ์–ด๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๋ฉ”์„œ๋“œ์ด๋‹ค. ๋™์ž‘ ๊ณผ์ •์„ ์ดํ•ดํ•˜๊ธฐ ์œ„ํ•ด ์•„๋ž˜ ๊ทธ๋ฆผ์—์„œ toss๋ผ๋Š” ๋‹จ์–ด๋ฅผ ๋“ฑ๋กํ•˜๋Š” ์˜ˆ์‹œ๋ฅผ ์ƒ๊ฐํ•ด๋ณด์ž.


insert("toss");

  1. currentNode๋ฅผ root ๋…ธ๋“œ๋กœ ์„ค์ •ํ•œ๋‹ค.

  2. ์ž…๋ ฅ๋œ ๋ฌธ์ž์—ด toss์˜ ๊ฐ ๋ฌธ์ž t, o, s, s๋ฅผ ํ•˜๋‚˜์”ฉ for๋ฌธ์œผ๋กœ ๋Œ ๊ฒƒ์ด๋‹ค.

    • t

      => ํ˜„์žฌ currentNode์˜ children ํ”„๋กœํผํ‹ฐ๊ฐ€ t๋ผ๋Š” key ๊ฐ’์— ํ•ด๋‹นํ•˜๋Š” value๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š”์ง€ ๊ฒ€์‚ฌํ•˜๊ณ , ํ˜„์žฌ๋Š” ์žˆ๊ธฐ ๋•Œ๋ฌธ์— currentNode๋ฅผ ํ•ด๋‹น children์— ๋“ค์–ด์žˆ๋Š” node์ค‘ key ๊ฐ’ t์— ํ•ด๋‹นํ•˜๋Š” node๋กœ ๋ฐ”๊ฟ”์ฃผ๊ณ , ์ด node๋Š” value ๊ฐ’์œผ๋กœ t๋ฅผ ๊ฐ€์งˆ ๊ฒƒ์ด๋‹ค.

    • o

      => ํ˜„์žฌ currentNode์˜ children ํ”„๋กœํผํ‹ฐ๊ฐ€ o๋ผ๋Š” key ๊ฐ’์— ํ•ด๋‹นํ•˜๋Š” value๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š”์ง€ ๊ฒ€์‚ฌํ•˜๊ณ , ํ˜„์žฌ๋Š” ์žˆ๊ธฐ ๋•Œ๋ฌธ์— currentNode๋ฅผ ํ•ด๋‹น children์— ๋“ค์–ด์žˆ๋Š” node ์ค‘ key ๊ฐ’ o์— ํ•ด๋‹นํ•˜๋Š”node๋กœ ๋ฐ”๊ฟ”์ฃผ๊ณ , ์ด node๋Š” value ๊ฐ’์œผ๋กœ to๋ฅผ ๊ฐ€์งˆ ๊ฒƒ์ด๋‹ค.

    • s

      => ํ˜„์žฌ currentNode์˜ children ํ”„๋กœํผํ‹ฐ๊ฐ€ s๋ผ๋Š” key ๊ฐ’์— ํ•ด๋‹นํ•˜๋Š” value๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š”์ง€ ๊ฒ€์‚ฌํ•˜๊ณ , ํ˜„์žฌ ๋…ธ๋“œ์ธ to๋Š” ์ž์‹ ๋…ธ๋“œ๊ฐ€ ์—†๊ธฐ ๋•Œ๋ฌธ์— ํ˜„์žฌ ๋…ธ๋“œ์˜ children map ๊ฐ์ฒด์— { key : "s" , value : Node() }์ธ ์š”์†Œ๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค.

      ์—ฌ๊ธฐ์„œ ์ด node๋Š” ๋“ฑ๋กํ•˜๋ ค๋Š” ๋‹จ์–ด toss๊ฐ€ ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์— node์˜ isWord ํ”„๋กœํผํ‹ฐ๋Š” false๋กœ ์„ค์ •ํ•ด์ค€๋‹ค. ๋“ฑ๋กํ•˜๋ ค๋Š” ๋‹จ์–ด์ธ์ง€ ํŒ๋‹จํ•˜๊ธฐ ์œ„ํ•ด, ๋“ฑ๋กํ•˜๋ ค๋Š” ๋‹จ์–ด string๊ณผ ๋…ธ๋“œ์˜ value ๊ฐ’์ด ๋  currentNode.value + char ๊ฐ’์„ ๋น„๊ตํ•ด์คฌ๋‹ค.

      const charForInsert = currentNode.value + char; // ๋‹ค์Œ node์— ์ž…๋ ฅ๋  value ๊ฐ’
      
      currentNode.children.set(
          char,
          new Node(charForInsert, charForInsert === string) 
      );
    • s

      ์œ„ s์™€ ๊ฐ™์€ ๊ณผ์ •์„ ๊ฑฐ์น˜๊ณ , ์—ฌ๊ธฐ์„œ๋Š”, isWord = true ์ธ ๊ฐ’์œผ๋กœ ๋…ธ๋“œ๊ฐ€ ์ถ”๊ฐ€๋œ๋‹ค.


3. ์ž๋™ ์™„์„ฑ ๊ธฐ๋Šฅ ๊ตฌํ˜„

levelOrder(node){ // level order
    const q = new Queue();
    q.enqueue(node);

    while(q.size()){
        const currentNode = q.dequeue();
        if(currentNode.isWord){ // ๋“ฑ๋ก๋œ ๋‹จ์–ด๋งŒ ์ถœ๋ ฅ
            console.log(currentNode.value); 
        }

        for(let key of currentNode.children.keys()){
            q.enqueue(currentNode.children.get(key));
        }
    }
}

autoComplete(string){
    // string์„ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” node๋ฅผ ์ฐพ์•„์„œ
    let node = this.find(string);
    // node๋ถ€ํ„ฐ ์ˆœํšŒ ์‹œ์ž‘ 
    console.log(`๊ฒ€์ƒ‰์–ด : ${string}`); 
    this.levelOrder(node);
}

leverOrder ๋ฉ”์„œ๋“œ

์‚ฌ์šฉ์ž๊ฐ€ ์ž…๋ ฅํ•œ ๋‹จ์–ด๋กœ๋ถ€ํ„ฐ ์ƒ์„ฑ๋  ์ˆ˜ ์žˆ๋Š” ์ถ”์ฒœ ๊ฒ€์ƒ‰์–ด๋“ค์„ ๊ธธ์ด์ˆœ์œผ๋กœ ์ถœ๋ ฅํ•ด ์ค„ ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— Queue๋ฅผ ์ด์šฉํ•œ lever order ์ˆœํšŒ๋ฅผ ๊ตฌํ˜„ํ–ˆ๋‹ค.

์ž…๋ ฅ๋œ node๋ถ€ํ„ฐ ์ž์‹ ๋…ธ๋“œ๋“ค์„ level order๋กœ ์ˆœํšŒํ•˜๋ฉด์„œ ๋“ฑ๋ก๋œ ๋‹จ์–ด์ผ ๋•Œ๋งŒ ์ถœ๋ ฅํ•ด์ฃผ์—ˆ๋‹ค.

if(currentNode.isWord){ // ๋“ฑ๋ก๋œ ๋‹จ์–ด๋งŒ ์ถœ๋ ฅ
    console.log(currentNode.value); 
}

autoComplete ๋ฉ”์„œ๋“œ

  1. ์šฐ์„  ์ž…๋ ฅ๋œ ๋ฌธ์ž์—ด string์„ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” node๋ฅผ ์ฐพ๊ณ 
  2. ์ด node๋ฅผ ์‹œ์ž‘์œผ๋กœ leverOrder ๋ฉ”์„œ๋“œ๋ฅผ ์‹คํ–‰ํ•˜๋ฉด

์ž๋™์™„์„ฑ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.


4. ๋‹จ์–ด ๋“ฑ๋ก ๋ฐ ์ž๋™ ์™„์„ฑ ํ…Œ์ŠคํŠธ

const trie = new Trie();
trie.insert("pro"); // ์ถœ๋ ฅ x
trie.insert("proto"); // ์ถœ๋ ฅ x
trie.insert("prou"); // ์ถœ๋ ฅ x
trie.insert("protorype");
trie.insert("programmers");
trie.insert("primary");
trie.insert("proud");
trie.insert("picnic");
trie.insert("plz dm");

trie.autoComplete("pro");

๋‚ด๊ฐ€ ๊ธฐ๋Œ€ํ•œ๋Œ€๋กœ ์ž˜ ๋™์ž‘ํ•˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค !


๐Ÿ™‡๐Ÿปโ€โ™‚๏ธ ์ฐธ๊ณ  ๋ฐ ์ด๋ฏธ์ง€ ์ถœ์ฒ˜

profile
๊พธ์ค€ํžˆ, ๊นŠ๊ฒŒ

0๊ฐœ์˜ ๋Œ“๊ธ€