관리 메뉴

Daehyunii's Dev-blog

15 μŠ€νƒ & 큐 λ³Έλ¬Έ

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

15 μŠ€νƒ & 큐

Daehyunii 2022. 8. 14. 15:54

15.1 μŠ€νƒ(Stack)

  μŠ€νƒμ΄λž€ ν›„μž…μ„ μΆœ 원칙을 λ”°λ₯΄λŠ” 데이터 ꡬ쑰λ₯Ό μΌμ»«λŠ” 말이닀. 즉, λ‚˜μ€‘μ— λ“€μ–΄μ˜¨ 데이터가 λ¨Όμ € μ œκ±°λ˜λŠ” λ°©μ‹μ˜ 자료 ꡬ쑰λ₯Ό μŠ€νƒμ΄λΌκ³  λ§ν•œλ‹€. 섀거지λ₯Ό ν•˜κΈ° μœ„ν•΄ μ‹±ν¬λŒ€μ— μŒ“μΈ 그릇 쀑 κ°€μž₯μœ„μ— μžˆλŠ” 그릇을 ν•˜λ‚˜μ”© 섀거지해 λ‚˜κ°„λ‹€κ³  μƒκ°ν•˜λ©΄ 쉽닀. μŠ€νƒμ„ μ½”λ”©ν•˜λŠ” 방법은 μ—¬λŸ¬κ°€μ§€κ°€ 있고 μ—°κ²° 리슀트λ₯Ό μ‚¬μš©ν•΄μ„œ κ΅¬ν˜„ν•  μˆ˜λ„ μžˆλ‹€. 즉, μŠ€νƒμ΄λΌλŠ” κ°œλ…μ€ ν›„μž…μ„ μΆœ 원칙을 μ§€ν‚€λŠ” 자료 ꡬ쑰듀을 λ§ν•˜λŠ” 좔상적인 κ°œλ…μ΄λ‹€. 

 

15.2 λ°°μ—΄λ‘œ μŠ€νƒ κ΅¬ν˜„ν•˜κΈ°

  배열을 λ§Œλ“€κ³  ν•΄λ‹Ή 배열에 데이터λ₯Ό μΆ”κ°€ν•  λ•Œ push() λ©”μ„œλ“œλ₯Ό ν™œμš©ν•˜κ³ , μ œκ±°ν•  λ•Œ pop() λ©”μ„œλ“œλ§Œμ„ μ‚¬μš©ν•˜κ±°λ‚˜ shift(), unshift() λ©”μ„œλ“œλ§Œμ„ μ‚¬μš©ν•œλ‹€λ©΄ 배열을 μŠ€νƒμœΌλ‘œ μ‚¬μš©ν•˜λŠ” 방법이 λœλ‹€. ν›„μž…μ„ μΆœ 원칙을 지킀고 있기 λ•Œλ¬Έμ΄λ‹€. λ‹€λ§Œ 배열을 μŠ€νƒμœΌλ‘œ ν™œμš©ν•˜λŠ” κ²½μš°μ—λŠ” push(),pop() λ©”μ„œλ“œλ₯Ό ν™œμš©ν•˜λŠ”κ²ƒμ΄ 더 μ’‹λ‹€.(인덱슀 λ•Œλ¬Έμ—)

var stack = [];
stack.push('a');
stack.push('b');
stack.push('c');
console.log(stack.pop()); // c
console.log(stack.pop()); // b
console.log(stack.pop()); // a

15.3 단일 μ—°κ²° 리슀트둜 μŠ€νƒ κ΅¬ν˜„ν•˜κΈ°

  μŠ€νƒμ€ ν›„μž…μ„ μΆœ ꡬ쑰 원칙을 지킀면 되기 λ•Œλ¬Έμ— 단일 μ—°κ²° λ¦¬μŠ€νŠΈλ‘œλ„ μŠ€νƒμ„ κ΅¬ν˜„ν•  수 μžˆλ‹€. λ‹€λ§Œ, 단일 μ—°κ²° 리슀트λ₯Ό μŠ€νƒμœΌλ‘œ κ΅¬ν˜„ν•˜κΈ° μœ„ν•΄μ„œλŠ” λ°°μ—΄κ³Ό λ‹€λ₯΄κ²Œ shift(), unshift()둜 κ΅¬ν˜„ν•˜λŠ”κ²ƒμ΄ μ’‹λ‹€. 단일 μ—°κ²° λ¦¬μŠ€νŠΈλŠ” μΈλ±μŠ€κ°€ μ—†κΈ° λ•Œλ¬Έμ— λ§ˆμ§€λ§‰μ— λ…Έλ“œλ₯Ό μ œκ±°ν•˜κΈ° μœ„ν•΄μ„œλŠ” ν…ŒμΌ λ…Έλ“œμ˜ 직전 λ…Έλ“œλ₯Ό μ°ΎκΈ°μœ„ν•΄ ν—€λ“œ λ…Έλ“œλΆ€ν„° μ‹œμž‘ν•΄μ„œ μ°Ύμ•„κ°€μ•Ό ν•˜λ―€λ‘œ O(N) μ‹œκ°„ λ³΅μž‘λ„λ₯Ό κ°–κ²Œ λ˜λ―€λ‘œ μ—°κ²° 리슀트의 맨 μ•žμ— λ…Έλ“œλ₯Ό μΆ”κ°€ν•˜κ³  μ œκ±°ν•˜λŠ” λ°©μ‹μœΌλ‘œ μŠ€νƒμ„ κ΅¬ν˜„ν•˜λŠ” 것이 더 νš¨μœ¨μ μ΄λ‹€.

class Stack {
    constructor(){
        this.first = null;
        this.last = null;
        this.size = 0;
    }
    unshift(val){ // 맨 μ•žμ— λ…Έλ“œ μΆ”κ°€
        var newNode = new Node(val);
        if(!this.first){
            this.first = newNode;
            this.last = newNode;
        } else {
            var temp = this.first;
            this.first = newNode;
            this.first.next = temp;
        }
        return ++this.size;
    }
    shift(){ // 맨 μ•žμ— λ…Έλ“œ μΆ”κ°€
        if(!this.first) return null; //λ…Έλ“œκ°€ μ—†λŠ”μ§€ 확인
        var temp = this.first;
        if(this.first === this.last){ //λ…Έλ“œκ°€ ν•˜λ‚˜μΈμ§€ 확인
            this.last = null;
        }
        this.first = this.first.next; //값이 ν•˜λ‚˜λΌλ©΄ μ• μ΄ˆμ— nextλŠ” nullμ΄λ―€λ‘œ
        // μœ„μ—μ„œλŠ” λ…Έλ“œκ°€ ν•˜λ‚˜μΈμ§€ ν™•μΈν•˜λŠ” κ³Όμ •μ—μ„œλŠ” last만 λ°”κΏ”μ£Όλ©΄ 됨
        this.size--;
        return temp.value;
    }
}

15.4 큐(Queue)

  큐도 μŠ€νƒκ³Ό λ§ˆμ°¬κ°€μ§€λ‘œ 데이터 κ΅¬μ‘°λ‘œμ„œ 데이터λ₯Ό μΆ”κ°€ν•˜κ³  μ œκ±°ν•œλ‹€. κ·Έλ ‡μ§€λ§Œ μŠ€νƒκ³ΌλŠ” λ‹€λ₯΄κ²Œ μ„ μž…μ„ μΆœ 방식이닀. 즉, λ¨Όμ € λ“€μ–΄κ°„ 것이 λ¨Όμ € λ‚˜κ²Œ λœλ‹€. μ—λ²„λžœλ“œ μž…μž₯을 μœ„ν•΄ 쀄 μ„œ μžˆλŠ”κ²ƒμ„ μƒκ°ν•˜λ©΄ μ΄ν•΄ν•˜κΈ° 쉽닀. μŠ€νƒκ³Ό λ§ˆμ°¬κ°€μ§€λ‘œ 배열을 μ΄μš©ν•΄μ„œ 큐λ₯Ό κ΅¬ν˜„ν•  수 있고 λ˜λŠ” 자체적으둜 큐λ₯Ό κ΅¬ν˜„ν•  μˆ˜λ„ μžˆλ‹€. νμ—μ„œλŠ” 보톡 데이터λ₯Ό μΆ”κ°€ν•˜κΈ° μœ„ν•΄ μ‚¬μš©λ˜λŠ” ν‚€μ›Œλ“œλ₯Ό enqueue, 데이터λ₯Ό μ œκ±°ν•˜κΈ° μœ„ν•΄ μ‚¬μš©ν•˜λŠ” ν‚€μ›Œλ“œλ₯Ό dequeue라고 ν•œλ‹€. 

 

β€»λ°°μ—΄μ˜ λ©”μ„œλ“œλ₯Ό μ΄μš©ν•˜μ—¬ μŠ€νƒ&큐 κ΅¬ν˜„ 정리

μŠ€νƒ(ν›„μž…μ„ μΆœ) 큐(μ„ μž…μ„ μΆœ)
push() & pop()  push() & shift()
shift() & unshift() unshift() & pop()

15.5 단일 μ—°κ²° 리슀트둜 큐 μž‘μ„±ν•˜κΈ°

  단일 μ—°κ²° 리슀트둜 큐λ₯Ό κ΅¬ν˜„ν•˜λ €λ©΄ λ°°μ—΄μ˜ push() & shift() λ©”μ„œλ“œμ²˜λŸΌ κΈ°λŠ₯을 κ΅¬ν˜„ν•˜λŠ”κ²ƒμ΄ μ’‹λ‹€. μ™œλƒν•˜λ©΄ 단일 μ—°κ²° 리슀트의 경우 λ’€μ—μ„œ 제거λ₯Ό ν•˜λ €λ©΄ ν—€λ“œ λ…Έλ“œλΆ€ν„° 타고 λ“€μ–΄κ°€μ•Ό ν•˜λ―€λ‘œ μ‹œκ°„μ΄ 였래 걸리기 λ•Œλ¬Έμ΄λ‹€. νλŠ” μ—„μ²­ 큰 데이터λ₯Ό 가지더라도 상관없닀. μΈλ±μŠ€κ°€ μ—†μœΌλ―€λ‘œ λͺ¨λ“  λͺ…령이 μƒμˆ˜κ°’μ„ κ°€μ§€κ²Œ λ˜λ―€λ‘œ μ „ν˜€ λ¬Έμ œκ°€ μ—†λ‹€. κ°€μž₯ 뒀에 λ„£κ³ , κ°€μž₯ μ•žμ—μ„œ μ œκ±°ν•˜λ―€λ‘œ 배열이 길어져도 항상 O(1) μ‹œκ°„ λ³΅μž‘λ„λ₯Ό κ°–λŠ”λ‹€. μŠ€νƒκ³Όμ˜ μ°¨μ΄λŠ” ν›„μž…μ„ μΆœμ΄λƒ μ„ μž…μ„ μΆœμ΄λƒμ˜ 차이이고 μ½”λ“œ κ΅¬ν˜„ 방식은 거의 λ™μΌν•˜λ‹€. 

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

class Queue {
    constructor(){
        this.first = null;
        this.last = null;
        this.size = 0;
    }
    enqueue(val){ //push 역할을 함
        var newNode = new Node(val);
        if(!this.first){
            this.first = newNode;
            this.last = newNode;
        } else {
            this.last.next = newNode;
            this.last = newNode;
        }
        return ++this.size;
    }

    dequeue(){ //shift 역할을 함
        if(!this.first) return null; // λ…Έλ“œκ°€ μ—†λŠ” 경우 확인

        var temp = this.first;
        if(this.first === this.last) { // λ…Έλ“œκ°€ ν•œκ°œμΈ 경우 확인
            this.last = null;
        }
        this.first = this.first.next;
        this.size--;
        return temp.value;
    }
}