ํ‹ฐ์Šคํ† ๋ฆฌ ๋ทฐ

728x90
๋ฐ˜์‘ํ˜•
์ฝ”๋”ฉ ํ…Œ์ŠคํŠธ ๋ฌธ์ œ๋ฅผ ํ’€๋ฉด์„œ PQ(Priority Queue)๋ฅผ ์ง์ ‘ ๊ตฌํ˜„ํ•˜์—ฌ์•ผ ํ•  ๊ฒฝ์šฐ๊ฐ€ ์žˆ์—ˆ๋‹ค. ๋‹จ์ˆœํžˆ Parent, Left Child, Right Child์˜ ์ธ๋ฑ์Šค๋งŒ ์•„๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๊ณ , push, pop, updaet, erase ๋ชจ๋“  ๊ธฐ๋Šฅ์— ๋Œ€ํ•ด ์–ด๋–ค ์‹์œผ๋กœ ๋™์ž‘ํ•˜๋Š”์ง€ ๊ฐ„๋žตํžˆ ์ •๋ฆฌํ•ด๋ณด๊ณ ์ž ํ•œ๋‹ค.

PQ์— ์‚ฝ์ž…ํ•  ๋ฐ์ดํ„ฐ

struct Info {
    int idx;
    int score;
}

 PQ์— ์‚ฝ์ž…ํ•  ๋ฐ์ดํ„ฐ๋Š” ์ผ๋ฐ˜ ๋ณ€์ˆ˜๊ฐ€ ์•„๋‹Œ, ์‚ฌ์šฉ์ž ์ง€์ • ๋ณ€์ˆ˜๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์ •๋ ฌ์ด ๊ฐ€๋Šฅํ•œ ๊ฒฝ์šฐ๋ฅผ ๋‹ค๋ฃจ๊ณ ์ž ํ•œ๋‹ค. ์œ„ ๊ตฌ์กฐ์ฒด ์ฒ˜๋Ÿผ score๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์ •๋ ฌ๋  ์ˆ˜ ๋„ ์žˆ๊ณ , ๊ฒฝ์šฐ์— ๋”ฐ๋ผ ๋‹ค์–‘ํ•œ ์šฐ์„ ์ˆœ์œ„์— ๋”ฐ๋ผ ์ •๋ ฌ์‹œํ‚ฌ ์ˆ˜ ์žˆ๋‹ค. `idx`์˜ ๊ฒฝ์šฐ, PQ์— push, pop์„ ํ•  ๋•Œ๋Š” ํ•„์š”ํ•˜์ง€ ์•Š์ง€๋งŒ, PQ์— update, erase ํ•  ๊ฒฝ์šฐ์— ํ•„์š”ํ•˜๋‹ค.

 

PQ init

void init() {
    // size๋ฅผ 0์œผ๋กœ ๋งŒ๋“ค๋ฉด top๋ถ€ํ„ฐ ๋‹ค์‹œ ์‚ฝ์ž…ํ•˜๊ฒŒ ๋œ๋‹ค.
    size = 0;
}

 PQ์— init๋Š” ๊ฐ„๋‹จํ•˜๋‹ค. ํ˜„์žฌ ์‚ฌ์šฉ์ค‘์ธ heap์˜ ํฌ๊ธฐ๋ฅผ 0์œผ๋กœ ๋งŒ๋“ค์–ด๋ฒ„๋ฆฌ๋ฉด top๋ถ€ํ„ฐ ๋‹ค์‹œ ๊ฐ’์„ ์ฑ„์šฐ๊ฒŒ ๋œ๋‹ค.

 

PQ Push

int updateParent(int idx) {
    int curIdx = idx;

    // current๊ฐ€ root๊ฐ€ ์•„๋‹ˆ๊ณ , parent ๋…ธ๋“œ๋ณด๋‹ค ์šฐ์„ ์ˆœ์œ„์ด๋ฉด
    while (curIdx > 0 && comp(curIdx, (curIdx - 1) / 2)) {
        swap(curIdx, (curIdx - 1) / 2);
        curIdx = (curIdx - 1) / 2;
    }

    return curIdx;
}

void push(Info* r) {
    heap[size] = r;
    r->idx = size;
    updateParent(size);
    size++;
}

 PQ์— ์ƒˆ๋กœ์šด ๊ฐ’์„ pushํ•œ ๊ฒฝ์šฐ, ํƒ์ƒ‰ํ•˜๊ณ ์ž ํ•˜๋Š” index๊ฐ€ root๊ฐ€ ์•„๋‹ˆ๊ณ , parent๋ณด๋‹ค ์šฐ์„ ์ˆ˜์œ„๊ฐ€ ๋†’์„ ๋•Œ๊นŒ์ง€ ๊ณ„์† ํƒ์ƒ‰ํ•˜์—ฌ, ํ˜„์žฌ ์‚ฝ์ž…ํ•œ ๊ฐ’์˜ ์ž๋ฆฌ๋ฅผ ์ฐพ์•„์•ผ ํ•œ๋‹ค. ์ด๋ฅผ ์œ„ํ•ด, `swap`, `comp` ํ•จ์ˆ˜๋ฅผ ์ •์˜ํ•˜์—ฌ ํ˜ธ์ถœํ•˜๋ฉด ๋ณด๋‹ค ๊น”๋”ํ•˜๊ฒŒ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค. ์—ฌ๊ธฐ์„œ ์ค‘์š”ํ•œ ๊ฒƒ์€ parent์˜ index๋Š” `(current index - 1) / 2`๋ผ๋Š” ๊ฒƒ์ด๋‹ค.

 

PQ pop

void updateChild(int idx) {
    int curIdx = idx;
    // current๊ฐ€ ์™ผ์ชฝ ์ž์‹์ด ์žˆ์„ ๋•Œ ๊นŒ์ง€
    while (curIdx * 2 + 1 < size) {
    int child;

    if (curIdx * 2 + 2 == size)
        child = curIdx * 2 + 1;
    else
        child = comp(curIdx * 2 + 1, curIdx * 2 + 2) ? curIdx * 2 + 1 : curIdx * 2 + 2;

    if (comp(curIdx, child))
        break;

        swap(curIdx, child);
        curIdx = child;
    }
}

Info* pop() {
    if (size == 0)
        return nullptr;

    Info* top = heap[0];
    size--;
    swap(0, size);
    updateChild(0);
    return top;
}

 PQ์˜ top์„ popํ•˜๋Š” ๊ฒฝ์šฐ์—๋Š” 0๋ฒˆ ์ธ๋ฑ์Šค์˜ ๊ฐ’์„ return ํ•˜๊ณ , 0๋ฒˆ๊ณผ ๋งˆ์ง€๋ง‰ ์ธ๋ฑ์Šค์™€ swap ํ•œ ๋’ค์—, ํ•ด๋‹น ๊ฐ’์˜ ์œ„์น˜๋ฅผ ์ฐพ์œผ๋ฉด์„œ ๋‹ค์‹œ ์ •๋ ฌํ•˜๋Š” ๊ณผ์ •์„ ๊ฑฐ์ณ์•ผ ํ•œ๋‹ค. ์—ฌ๊ธฐ์„œ ์ค‘์š”ํ•œ ๊ฒƒ์€ left child๋Š” `current index * 2 + 1`, right child๋Š” `current index * 2 + 2`๋กœ ์ฐพ์„ ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.

 

PQ update

  PQ update๋Š” heap์˜ ํŠน์ • ์ธ๋ฑ์Šค์— ๋Œ€ํ•œ ๊ฐ’์ด ์—…๋ฐ์ดํŠธ ๋˜๋ฉด, `updateChild(updateParent(idx))`์™€ ๊ฐ™์ด ํŠน์ • ์ธ๋ฑ์Šค์— ๋Œ€ํ•œ ์œ„์น˜๋ฅผ ๋‹ค์‹œ ์ •๋ ฌํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ์ง„ํ–‰ํ•˜๋ฉด ๋œ๋‹ค.

 

PQ erase

 PQ erase๋Š” pop์€ 0๋ฒˆ ์ธ๋ฑ์Šค์™€ ๋งˆ์ง€๋ง‰ ์ธ๋ฑ์Šค๋ฅผ swapํ•˜์˜€๋‹ค๋ฉด, ์ด์™€ ๋‹ฌ๋ฆฌ ํŠน์ • ์ธ๋ฑ์Šค์™€ ๋งˆ์ง€๋ง‰ ์ธ๋ฑ์Šค๋ฅผ swap ํ•˜๋Š” ์ฐจ์ด๋งŒ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค. update์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์ค‘๊ฐ„ ์ธ๋ฑ์Šค์— erase๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค๋ฉด, child, parent ๋ชจ๋‘ ์—…๋ฐ์ดํŠธํ•˜์—ฌ์•ผ ํ•˜๋ฏ€๋กœ `updateChild(updateParent(idx))`์™€ ๊ฐ™์ด ํ˜ธ์ถœํ•˜์—ฌ ๋‹ค์‹œ ์ •๋ ฌํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ์ง„ํ–‰ํ•œ๋‹ค.

 

์ „์ฒด ์ฝ”๋“œ

#define MAX_HEAP	100

struct Info {
    int idx;
    int score;
};

struct PQ {
    /*
    *  Parent = (idx - 1) / 2
    *  leftChild = idx * 2 + 1
    *  rightChild = idx * 2 + 2
    */
    int size;
    Info* heap[MAX_HEAP];

    void init() {
        // size๋ฅผ 0์œผ๋กœ ๋งŒ๋“ค๋ฉด top๋ถ€ํ„ฐ ๋‹ค์‹œ ์‚ฝ์ž…ํ•˜๊ฒŒ ๋œ๋‹ค.
        size = 0;
    }

    bool comp(int a, int b) {
        // ๋ถ€๋“ฑํ˜ธ๋ฅผ ๋ฐ˜๋Œ€๋กœํ•˜๋ฉด max heap์ด ๋œ๋‹ค.
        return heap[a]->score < heap[b]->score;
    }

    void swap(int a, int b) {
        heap[a]->idx = b;
        heap[b]->idx = a;
        Info* temp = heap[a];
        heap[a] = heap[b];
        heap[b] = temp;
    }

    int updateParent(int idx) {
        int curIdx = idx;

        // current๊ฐ€ root๊ฐ€ ์•„๋‹ˆ๊ณ , parent ๋…ธ๋“œ๋ณด๋‹ค ์šฐ์„ ์ˆœ์œ„์ด๋ฉด
        while (curIdx > 0 && comp(curIdx, (curIdx - 1) / 2)) {
            swap(curIdx, (curIdx - 1) / 2);
            curIdx = (curIdx - 1) / 2;
        }

        return curIdx;
    }

    void updateChild(int idx) {
        int curIdx = idx;
        // current๊ฐ€ ์™ผ์ชฝ ์ž์‹์ด ์žˆ์„ ๋•Œ ๊นŒ์ง€
        while (curIdx * 2 + 1 < size) {
            int child;

            if (curIdx * 2 + 2 == size)
                child = curIdx * 2 + 1;
            else
                child = comp(curIdx * 2 + 1, curIdx * 2 + 2) ? curIdx * 2 + 1 : curIdx * 2 + 2;

            if (comp(curIdx, child))
                break;

            swap(curIdx, child);
            curIdx = child;
        }
    }

    void push(Info* r) {
        heap[size] = r;
        r->idx = size;
        updateParent(size);
        size++;
    }

    Info* pop() {
        if (size == 0)
            return nullptr;

        Info* top = heap[0];
        size--;
        swap(0, size);
        updateChild(0);
        return top;
    }
    /*
    * update, erase๋Š” ํŠน์ •๋ถ€๋ถ„์—์„œ ์ง„ํ–‰๋˜๋ฏ€๋กœ
    * parent, child ๋ชจ๋‘ ์—…๋ฐ์ดํŠธ๋ฅผ ํ•˜์—ฌ์•ผ ํ•จ.
    */
    void update(Info* r) {
        updateChild(updateParent(r->idx));
    }

    void erase(Info* r) {
        int idx = r->idx;
        size--;
        swap(idx, size);
        updateChild(updateParent(idx));
    }
};

 ์ „์ฒด ์ฝ”๋“œ๋Š” ์œ„์™€ ๊ฐ™๋‹ค. ๋ฐ์ดํ„ฐ์˜ ์‚ฝ์ž…, ์‚ญ์ œ, ๊ฐฑ์‹ ์— ๋”ฐ๋ผ parent, child๋ฅผ ์—…๋ฐ์ดํŠธํ• ์ง€ ์•Œ๊ณ , ์ด๋ฅผ ํƒ์ƒ‰ํ•˜๊ธฐ ์œ„ํ•œ ๋กœ์ง์„ ์œ„ํ•ดํ•œ๋‹ค๋ฉด ์‰ฝ๊ฒŒ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค. update, erase๋ฅผ ์œ„ํ•ด์„œ๋Š” ํ•จ์ˆ˜๋ฅผ ์ž˜ ๊ตฌ๋ถ„ํ•˜์—ฌ ๊ตฌํ˜„ํ•˜๋Š” ๊ฒƒ๋„ ์ค‘์š”ํ•œ ๊ฒƒ ๊ฐ™๋‹ค.

728x90
๋ฐ˜์‘ํ˜•
๋Œ“๊ธ€
๊ธ€ ๋ณด๊ด€ํ•จ
์ตœ๊ทผ์— ์˜ฌ๋ผ์˜จ ๊ธ€
์ตœ๊ทผ์— ๋‹ฌ๋ฆฐ ๋Œ“๊ธ€