DevLog ๐Ÿ“จ/DataStructure

[DevLog][DS]Red Black Tree: Operation

cece00 2023. 9. 5. 22:47

Red Black Tree

1. Concept [revisited]

๋‹ค์Œ๊ณผ ๊ฐ™์€ ์„ฑ์งˆ์„ ๋งŒ์กฑํ•˜๋Š” ์ด์ง„ ๊ฒ€์ƒ‰ ํŠธ๋ฆฌ BST

  1. ๋ชจ๋“  ๋…ธ๋“œ๋Š” red or black
  2. root ๋…ธ๋“œ๋Š” black
  3. leaf (nil)๋…ธ๋“œ๋Š” black
  4. red ๋…ธ๋“œ์˜ ์ž์‹์€ black
  5. ํ•œ ๋…ธ๋“œ์—์„œ leaf(nil)๋กœ ๊ฐ€๋Š” ๊ฐ ๊ฒฝ๋กœ์— ํฌํ•จ๋œ black ๋…ธ๋“œ์˜ ๊ฐœ์ˆ˜๋Š” ๋ชจ๋‘ ๊ฐ™๋‹ค.

2. Operations

typedef enum {RBTREE_BLACK, RBTREE_RED} color_t;
typedef int key_t;

typedef struct node_t {
    key_t key;
    color_t color;
    struct node_t* parent;
    struct node_t* left;
    struct node_t* right;
}

typedef struct rbtree {
    node_t* root;
    node_t* nil;
}    

์œ„์™€ ๊ฐ™์€ ๊ตฌ์กฐ๋ฅผ ๊ฐ€์ •ํ•˜์ž. ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์—ฐ์‚ฐ์ด red black ํŠธ๋ฆฌ์˜ ๊ธฐ๋ณธ ์—ฐ์‚ฐ์ด๋‹ค.

rbtree* new_rbtree();
void free_rbtree(rbtree*);

node_t* rbtree_insert(rbtree*, key_t);
int* rbtree_delete(rbtree*, node_t*);
node_t* rbtree_find(const rbtree*, key_t);
node_t* rbtree_min(const rbtree*);
node_t* rbtree_max(const rbtree*);

int rbtree_to_array(rbtree*, key_t*, int);
  1. new_rbtree: ํŠธ๋ฆฌ์˜ ์ƒ์„ฑ
  2. free_rbtree: ํŠธ๋ฆฌ์˜ ์‚ญ์ œ (๋ฉ”๋ชจ๋ฆฌ ํ•ด์ œ)
  3. rbtree_insert: ํŠธ๋ฆฌ์— ์ƒˆ๋กœ์šด ๋…ธ๋“œ ์‚ฝ์ž…
  4. rbtree_delete: ํŠธ๋ฆฌ์— ์žˆ๋Š” ๋…ธ๋“œ ์‚ญ์ œ
  5. rbtree_find: ํŠธ๋ฆฌ์—์„œ ํ‚ค ๊ฐ’์„ ๊ฐ–๋Š” ๋…ธ๋“œ ๊ฒ€์ƒ‰
  6. rbtree_min/rbtree_max: ํŠธ๋ฆฌ์˜ ์ตœ์†Œ/์ตœ๋Œ€๊ฐ’ ๋ฐ˜ํ™˜
  7. rbtree_to_array: ํŠธ๋ฆฌ๋ฅผ ํ‚ค ๊ฐ’ ์˜ค๋ฆ„์ฐจ์ˆœ์œผ๋กœ ๋ฐฐ์—ด์— ๋‹ด์•„ ๋ฐ˜ํ™˜

์ด์ค‘์—์„œ find, min/max, array ์—ฐ์‚ฐ์€ read-only ์—ฐ์‚ฐ์œผ๋กœ, ์ผ๋ฐ˜ ์ด์ง„๊ฒ€์ƒ‰ํŠธ๋ฆฌ์™€ ๋™์ผํ•˜๊ฒŒ ์ฒ˜๋ฆฌํ•ด์ค„ ์ˆ˜ ์žˆ๋‹ค. ํŠธ๋ฆฌ์˜ ์ƒ์„ฑ๊ณผ ์‚ญ์ œ ์—ญ์‹œ ๋งˆ์ฐฌ๊ฐ€์ง€๋‹ค. ์ค‘์š”ํ•œ ๋ถ€๋ถ„์€ ๋…ธ๋“œ์˜ ์‚ฝ์ž…/์‚ญ์ œ ์—ฐ์‚ฐ์ธ๋ฐ, ์ด๋Š” ํŠธ๋ฆฌ์— ๋ณ€ํ™”๋ฅผ ๊ฐ€ํ•˜๋Š” ์—ฐ์‚ฐ์œผ๋กœ์„œ ์—ฐ์‚ฐ ํ›„์—๋„ red black ์„ฑ์งˆ์„ ๋งŒ์กฑํ•  ์ˆ˜ ์žˆ๋„๋ก ๋ณด์žฅํ•ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.




3. Insertion ์‚ฝ์ž…

1. Basic Idea

  1. ์ผ๋ฐ˜ ์ด์ง„ ํƒ์ƒ‰ ํŠธ๋ฆฌ์™€ ๊ฐ™์ด ๋…ธ๋“œ๋ฅผ ์‚ฝ์ž…ํ•  ๊ณณ์„ ์ฐพ๋Š”๋‹ค.
  2. ์‚ฝ์ž…ํ•œ ๋…ธ๋“œ๊ฐ€ red black ์†์„ฑ์„ ์œ„๋ฐ˜ํ•˜๋Š”์ง€ ๊ฒ€์‚ฌํ•œ๋‹ค.
  3. ์œ„๋ฐ˜ํ•  ๊ฒฝ์šฐ, ์†์„ฑ์„ ๋ณต๊ตฌํ•œ๋‹ค.

2. Rule Violation

์ƒˆ๋กœ์šด ๋…ธ๋“œ์˜ ์ƒ‰์„ red๋กœ ์„ค์ •ํ•˜๊ณ  ์‚ฝ์ž…์‹œํ‚ค๋ฏ€๋กœ, ๋‘ ๊ฐ€์ง€ ์†์„ฑ์ด ์œ„๋ฐ˜๋  ์ˆ˜ ์žˆ๋‹ค.

  1. Rule 2: ๋ฃจํŠธ๋ฅผ ์‚ฝ์ž…ํ–ˆ๋‹ค๋ฉด, ๋ฃจํŠธ๊ฐ€ black์ด์–ด์•ผ ํ•œ๋‹ค๋Š” ์†์„ฑ์„ ์œ„๋ฐ˜ํ•œ๋‹ค.
  2. Rule 4: red์ธ ๋…ธ๋“œ์˜ ์ž์‹์œผ๋กœ ์ƒˆ๋กœ์šด ๋…ธ๋“œ๋ฅผ ์‚ฝ์ž…ํ•  ์ˆ˜ ์žˆ๋‹ค.

์ด ๋‘ ๊ฐ€์ง€ ์œ„๋ฐ˜์€ ๋™์‹œ์— ์ผ์–ด๋‚˜์ง€ ์•Š๋Š”๋‹ค ์ฆ‰ 2๊ฐ€ ์œ„๋ฐ˜๋˜๋ฉด 4๋Š” ์ง€์ผœ์ง€๋Š”๋ฐ, ์ด๋Š” 2๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๊ฒฝ์šฐ๋Š” ๋นˆ ํŠธ๋ฆฌ์— ๋ฃจํŠธ๊ฐ€ ์‚ฝ์ž…๋˜๋Š” ๊ฒฝ์šฐ๋ฐ–์— ์—†๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ๋˜ํ•œ 4๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๊ฒฝ์šฐ, red ๋…ธ๋“œ๋Š” ๋ฃจํŠธ๊ฐ€ ๋  ์ˆ˜ ์—†๊ณ , ์†์„ฑ ์œ„๋ฐ˜์€ ์ƒˆ๋กœ์šด ๋…ธ๋“œ์™€ ๊ทธ ๋ถ€๋ชจ ์‚ฌ์ด์—์„œ๋งŒ ์ผ์–ด๋‚˜๋ฏ€๋กœ ๋ฃจํŠธ๊ฐ€ black์ด์–ด์•ผ ํ•œ๋‹ค๋Š” 2๋ฒˆ ๊ทœ์น™์€ ์ง€์ผœ์ง€๊ฒŒ ๋œ๋‹ค.

๋งŒ์•ฝ ์‚ฝ์ž…ํ•œ ๋…ธ๋“œ z์˜ ๋ถ€๋ชจ๊ฐ€ black ๋…ธ๋“œ๋ผ๋ฉด, ์†์„ฑ์„ ์œ„๋ฐ˜ํ•˜์ง€ ์•Š๋Š”๋‹ค. ์œ„ ๊ฒฝ์šฐ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์‚ฝ์ž…ํ•œ ๋…ธ๋“œ z์˜ ๋ถ€๋ชจ๊ฐ€ red๋ผ๋ฉด, fixup ์—ฐ์‚ฐ์„ ํ†ตํ•ด ์œ„ ๋‘ ๊ฐ€์ง€ ์œ„๋ฐ˜์„ ๊ฒ€์‚ฌํ•˜๊ณ  ์ˆ˜์ •ํ•ด์•ผ ํ•œ๋‹ค. fixup์˜ ์ผ€์ด์Šค๋Š” ์ด 6๊ฐœ๋กœ, 1-3์ผ€์ด์Šค๋Š” 4-6์ผ€์ด์Šค์™€ ๋Œ€์นญ์ด๋‹ค.

rbtree_insert_fixup(t, z)
    while z.parent.color == RED
        if z.parent == z.parent.parent.left
            u = z.parent.parent.right           // uncle
            if u.color == RED                   // case 1
                z.parent.color = BLACK
                u.color = BLACK
                z.parent.parent.color = RED
                z = z.parent.paret
            else if z = z.parent.right          // case 2
                    z = z.parent
                    rotate_left(t, z)
                z.parent.color = BLACK          // case 3
                z.parent.parent.color = RED
                rotate_right(t, z.parent.parent)
      else
          if z.parent == z.parent.parent.right
            u = z.parent.parent.left // uncle
            if u.color == RED                   // case 4
                z.parent.color = BLACK
                u.color = BLACK
                z.parent.parent.color = RED
                z = z.parent.parent
            else if z = z.parent.left           // case 5
                    z = z.parent
                    rotate_right(t, z)
                z.parent.color = BLACK          // case 6
                z.parent.parent.color = RED
                rotate_left(t, z.parent.parent)

    t.root.color = BLACK

๐Ÿ‘€ while ๋ฃจํ”„ ์•ˆ์—์„œ z.parent.parent๊ฐ€ ํ•ญ์ƒ ์กด์žฌํ•˜๋Š” ์ด์œ ๋Š”? while ๋ฃจํ”„๋กœ ์ง„์ž…ํ•จ๊ณผ ๋™์‹œ์— z์™€ z.parent์˜ ์ƒ‰์€ RED์ž„์ด ๋ณด์žฅ๋œ๋‹ค. ์‚ฝ์ž… ์—ฐ์‚ฐ ์ด์ „์˜ ํŠธ๋ฆฌ๋Š” red black์˜ ์„ฑ์งˆ์„ ๋งŒ์กฑํ•˜๋ฏ€๋กœ z.parent.parent๋Š” black์ด๊ณ , ํ•ญ์ƒ ์กด์žฌํ•œ๋‹ค. (red์ธ z.parent๊ฐ€ root๊ฐ€ ๋  ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.)

๋Œ€์นญ์ธ 1-3๋งŒ ๋ณด์ธ๋‹ค. ๋จผ์ € ์‚ผ์ดŒ ๋…ธ๋“œ๋ฅผ ์ •์˜ํ•œ๋‹ค.
u = x.parent.parent.right (x.parent.parent.left = x.parent์ธ ๊ฒฝ์šฐ)

CASE 1: u๊ฐ€ red์ธ ๊ฒฝ์šฐ

  • z.parent.color = BLACK
  • u.color = BLACK
  • z.parent.parent.color = RED
  • z = z.parent.parent

CASE1์—์„œ๋Š” red parent - red child์ธ ๊ฒฝ์šฐ๋ฅผ ํ•ด์†Œํ•œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  z = z.parent.parent๋ฅผ ํ†ตํ•ด 2๋‹จ๊ณ„ ์œ„๋กœ ์˜ฌ๋ผ๊ฐ„๋‹ค. ๋งŒ์•ฝ ์˜ฌ๋ผ๊ฐ„ z์˜ ๋ถ€๋ชจ๊ฐ€ red๋ผ๋ฉด while์— ๋‹ค์‹œ ์ง„์ž…ํ•˜๊ณ , ์•„๋‹ ๊ฒฝ์šฐ ์ข…๋ฃŒํ•œ๋‹ค.

CASE 2: u๊ฐ€ black์ด๊ณ  z๊ฐ€ ๋ถ€๋ชจ์˜ right child์ธ ๊ฒฝ์šฐ

  • z = z.parent
  • rotate_left(t, z);

CASE2๋Š” CASE3๋ฅผ ์˜ˆ๋น„ํ•œ๋‹ค. z๋ฅผ ํ•œ ๋‹จ๊ณ„ ์œ„๋กœ ์˜ฌ๋ ค์ค€ ํ›„ left๋กœ ๋Œ๋ฆฐ๋‹ค. z๋ฅผ ํ•œ๋‹จ๊ณ„ ์œ„๋กœ ์˜ฌ๋ฆฌ๋Š” ์ด์œ ๋Š”, CASE3 ์ง„์ž…์„ ์œ„ํ•ด z์™€ z.parent๊ฐ€ red์ธ ์ƒํ™ฉ์„ ๋งŒ๋“ค์–ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

CASE 3. u๊ฐ€ black์ด๊ณ  z๊ฐ€ ๋ถ€๋ชจ์˜ left child์ธ ๊ฒฝ์šฐ

  • z.parent.color = BLACK
  • z.parent.parent.color = RED
  • rotate_right(t, z.parent.parent)

CASE3๋Š” ์œ„์˜ ๊ณผ์ •์„ ํ†ตํ•ด red parent - red child์˜ ์œ„๋ฐ˜์„ ํ•ด๊ฒฐํ•œ๋‹ค.

๐Ÿค” root๊ฐ€ red์ธ ์œ„๋ฐ˜์€ ์–ด๋–ป๊ฒŒ ํ•ด์†Œ๋ ๊นŒ? z == root์ธ ๊ฒฝ์šฐ z.parent.color == RED๋ผ๋Š” ์กฐ๊ฑด์— ๋ถ€ํ•ฉํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ while๋ฌธ์— ์ง„์ž…ํ•˜์ง€ ์•Š๋Š”๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋งˆ์ง€๋ง‰ ๋ผ์ธ์ธ t.root.color = BLACK์„ ํ†ตํ•ด ์œ„๋ฐ˜์„ ํ•ด์†Œํ•œ๋‹ค.




4. Deletion ์‚ญ์ œ

1. Basic Idea

  1. ์ผ๋ฐ˜ ์ด์ง„ ํƒ์ƒ‰ ํŠธ๋ฆฌ์™€ ๊ฐ™์ด ๋…ธ๋“œ๋ฅผ ์‚ญ์ œํ•œ๋‹ค.
  2. ์‚ญ์ œ๋œ ๋…ธ๋“œ๋ฅผ ๋Œ€์ฒดํ•˜๋Š” ๋…ธ๋“œ๊ฐ€ red black ์†์„ฑ์„ ์œ„๋ฐ˜ํ•˜๋Š”์ง€ ๊ฒ€์‚ฌํ•œ๋‹ค.
  3. ์œ„๋ฐ˜ํ•  ๊ฒฝ์šฐ, ์†์„ฑ์„ ๋ณต๊ตฌํ•œ๋‹ค.

2. Rule Violation

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

์ด๋ฆ„ ์„ค๋ช…
z ๋‚ด๊ฐ€ ์‚ญ์ œํ•˜๋ ค๋Š” key๊ฐ’์„ ๊ฐ€์ง„ ๋…ธ๋“œ
y ํŠธ๋ฆฌ์—์„œ ์‚ญ์ œ๋˜๋Š” ๋…ธ๋“œ
x ์‚ญ์ œ๋œ ์ž๋ฆฌ๋ฅผ ๋Œ€์ฒดํ•˜๋Š” ๋…ธ๋“œ

[์ผ๋ฐ˜ ์ด์ง„๊ฒ€์ƒ‰ํŠธ๋ฆฌ์˜ ์‚ญ์ œ ์—ฐ์‚ฐ]

  1. leaf ๋…ธ๋“œ์ผ๋•Œ๋Š” ์‚ญ์ œํ•œ๋‹ค.
  2. ์ž์‹์ด ํ•˜๋‚˜๋งŒ ์žˆ์„ ๋•Œ๋Š” ์ž์‹์„ ์ž์‹ ์˜ ์œ„์น˜๋กœ ๊ต์ฒดํ•˜๊ณ  ์ž์‹ ์„ ์‚ญ์ œํ•œ๋‹ค.
  3. ์ž์‹์ด ๋‘˜ ๋‹ค ์žˆ์„ ๋•Œ๋Š” ์˜ค๋ฅธ์ชฝ ์„œ๋ธŒํŠธ๋ฆฌ์—์„œ ์ตœ์†Ÿ๊ฐ’์„ ์ฐพ์•„ ์ž์‹ ๊ณผ ๊ต์ฒดํ•˜๊ณ  ์ตœ์†Ÿ๊ฐ’ ๋…ธ๋“œ๋ฅผ ์‚ญ์ œํ•œ๋‹ค.
    3.1. ์ตœ์†Ÿ๊ฐ’ ๋…ธ๋“œ๋Š” left ์ž์‹์„ ๊ฐ–์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ํ•ญ์ƒ 1๋ฒˆ ๋˜๋Š” 2๋ฒˆ ์ผ€์ด์Šค์— ํ•ด๋‹นํ•œ๋‹ค.
    3.2. ์ž์‹ ์˜ ์™ผ์ชฝ ์„œ๋ธŒํŠธ๋ฆฌ์—์„œ ์ตœ๋Œ“๊ฐ’์„ ์ฐพ์•„ ๊ต์ฒดํ•ด๋„ ๋œ๋‹ค. ์ด ๊ฒฝ์šฐ์—๋„ ์ตœ๋Œ“๊ฐ’ ๋…ธ๋“œ๋Š” right์ž์‹์„ ๊ฐ–์ง€ ์•Š๋Š”๋‹ค.

์ผ๋ฐ˜ ์ด์ง„๊ฒ€์ƒ‰ํŠธ๋ฆฌ์—์„œ ๋…ธ๋“œ๋ฅผ ์‚ญ์ œํ•  ๋•Œ, 1๋ฒˆ, 2๋ฒˆ ์ผ€์ด์Šค์— ํ•ด๋‹นํ•˜๋Š” ๊ฒฝ์šฐ z์™€ y๋Š” ์„œ๋กœ ๊ฐ™๋‹ค. ์ด ๊ฒฝ์šฐ y = z ๋กœ ๋ณด๊ณ , x = y.child ๋กœ ์„ค์ •ํ•ด ์ค€๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ 3๋ฒˆ ์ผ€์ด์Šค์—์„œ๋Š” z์™€ y๋ฅผ ๊ตฌ๋ถ„ํ•ด์•ผ ํ•œ๋‹ค. z์˜ ์œ„์น˜์— y = ์˜ค๋ฅธ์ชฝ ์„œ๋ธŒํŠธ๋ฆฌ์˜ ์ตœ์†Ÿ๊ฐ’์ด ์˜ฎ๊ฒจ์ง€๊ณ , ๊ฒฐ๊ตญ ์‚ญ์ œ๋˜๋Š” ๊ฒƒ์€ y์ด๋ฏ€๋กœ y์˜ ์ž๋ฆฌ๋ฅผ ๋Œ€์ฒดํ•˜๋Š” x๋Š” x = y.right ์ด ๋˜์–ด์•ผ ํ•œ๋‹ค.

์œ„ ๊ทธ๋ฆผ์—์„œ ํ‚ค๊ฐ’์ด 1์ธ ๋…ธ๋“œ๋‚˜ 2์ธ ๋…ธ๋“œ์˜ ๊ฒฝ์šฐ, ๊ทธ ์ž์‹ ์ด ์‚ญ์ œ๋˜๋Š” ๋…ธ๋“œ์ด๋‹ค. ํ•˜์ง€๋งŒ 12๋ฅผ ํ‚ค๊ฐ’์œผ๋กœ ๊ฐ–๋Š” ๋…ธ๋“œ๋ฅผ ์‚ญ์ œํ•˜๋Š” ๊ณผ์ • ์ค‘์— ์ •๋ง๋กœ ์‚ญ์ œ๋˜๋Š” ๋…ธ๋“œ๋Š” 12์˜ ์˜ค๋ฅธ์ชฝ ์„œ๋ธŒํŠธ๋ฆฌ์˜ ์ตœ์†Ÿ๊ฐ’์ธ 14๋‹ค. ๋”ฐ๋ผ์„œ y๋ฅผ 14๋ฒˆ ๋…ธ๋“œ๋กœ ์„ค์ •ํ•˜๊ณ , y์˜ ์ƒ‰์„ ๋ณด์•„์•ผ ํ•œ๋‹ค. red black ํŠธ๋ฆฌ์˜ ๊ฐ€์žฅ ํ•ต์‹ฌ์ ์ธ ์กฐ๊ฑด์ธ ํ•œ ๋…ธ๋“œ์—์„œ ๋ฆฌํ”„๊นŒ์ง€๋กœ ๊ฐ€๋Š” ๊ฐ ๊ฒฝ๋กœ์˜ black height๊ฐ€ ๋ชจ๋‘ ๊ฐ™๋‹ค๋Š” ์กฐ๊ฑด์„ ์ง€ํ‚ค๊ธฐ ์œ„ํ•ด์„œ๋Š”, ์‹ค์ œ๋กœ ์‚ญ์ œ๋˜๋Š” (๊ทธ๋ž˜์„œ ๊ทธ ์ž์‹๊ณผ ๋ถ€๋ชจ๊ฐ€ ์„œ๋กœ ์—ฐ๊ฒฐ๋˜๋Š”) ๋…ธ๋“œ์˜ ์ƒ‰์ด ์ค‘์š”ํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

๋…ธ๋“œ๋ฅผ ์‚ญ์ œํ•  ๊ฒฝ์šฐ, ์‚ญ์ œ๋˜๋Š” ๋…ธ๋“œ์˜ ์ƒ‰์ด black์ธ์ง€, red์ธ์ง€์— ๋”ฐ๋ผ ์†์„ฑ ์œ„๋ฐ˜ ์—ฌ๋ถ€๊ฐ€ ๊ฒฐ์ •๋œ๋‹ค. ๋งŒ์•ฝ ์‚ญ์ œ๋œ ๋…ธ๋“œ๊ฐ€ red์ธ ๊ฒฝ์šฐ์—๋Š” ์œ„๋ฐ˜์ด ๋ฐœ์ƒํ•˜์ง€ ์•Š๋Š”๋ฐ, ๊ทธ ์ด์œ ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

์‚ญ์ œ๋œ ๋…ธ๋“œ y๊ฐ€ red๋ผ๊ณ  ํ•  ๋•Œ,

  1. y.parent ์—์„œ ์„œ๋ธŒํŠธ๋ฆฌ๋กœ ๊ฐ€๋Š” ๊ฐ ๊ฒฝ๋กœ์˜ black height๋Š” ๋ณ€ํ•จ์ด ์—†์œผ๋ฏ€๋กœ 5๋ฒˆ ์†์„ฑ์ด ๋ณด์กด๋œ๋‹ค.
  2. y.color == red์ด๋ฏ€๋กœ, y.left/y.right์™€ y.parent์˜ ์ƒ‰์€ black์ด๋‹ค. ๋”ฐ๋ผ์„œ y๊ฐ€ ์‚ญ์ œ๋˜๊ณ , y์˜ ์ž์‹ ์ค‘ ํ•˜๋‚˜๊ฐ€ y๋ฅผ ๋Œ€์ฒดํ•˜๊ฒŒ ๋˜์–ด๋„ ์†์„ฑ4๋ฅผ ์œ„๋ฐ˜ํ•˜์ง€ ์•Š๋Š”๋‹ค.
  3. y๋Š” leaf ๋˜๋Š” root๊ฐ€ ์•„๋‹ˆ๋ฏ€๋กœ 2, 3๋ฒˆ ์†์„ฑ์ด ๋ณด์กด๋œ๋‹ค. ์ƒ‰์˜ ๋ณ€ํ™”๊ฐ€ ์—†์œผ๋ฏ€๋กœ 1๋ฒˆ ์†์„ฑ๋„ ๋งˆ์ฐฌ๊ฐ€์ง€.

ํ•˜์ง€๋งŒ ์‚ญ์ œ๋œ ๋…ธ๋“œ๊ฐ€ black์ด๋ผ๋ฉด, ์‚ญ์ œ ํ›„ red black์˜ ์†์„ฑ์„ ๋ณต๊ตฌํ•˜๋Š” ์—ฐ์‚ฐ์ด ํ•„์š”ํ•˜๋‹ค.

  1. Rule 2: ์‚ญ์ œ๋œ ๋…ธ๋“œ๊ฐ€ ๋ฃจํŠธ์ธ ๊ฒฝ์šฐ, ๋ฃจํŠธ๊ฐ€ black์ด์–ด์•ผ ํ•œ๋‹ค๋Š” ์กฐ๊ฑด์ด ์œ„๋ฐ˜๋  ์ˆ˜ ์žˆ๋‹ค.
  2. Rule 4: ํ•œ ๋…ธ๋“œ๊ฐ€ ์‚ญ์ œ๋˜๊ณ  ๋‚˜์„œ ๊ทธ ์ž์‹๊ณผ ๋ถ€๋ชจ๊ฐ€ ์—ฐ๊ฒฐ๋˜์—ˆ์„ ๋•Œ, Red์˜ ์ž์‹์ด Red์ธ ๊ฒฝ์šฐ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค.
  3. Rule 5: ํ•œ ๋…ธ๋“œ๊ฐ€ ์‚ญ์ œ๋˜๊ณ  ๋‚˜์„œ, ๊ทธ ๋ถ€๋ชจ๋กœ๋ถ€ํ„ฐ ๋ฆฌํ”„๋กœ ๊ฐ€๋Š” black height์ด ์„œ๋กœ ๋‹ฌ๋ผ์งˆ ์ˆ˜ ์žˆ๋‹ค.

Rule 5์˜ ์œ„๋ฐ˜์„ ์ˆ˜์ •ํ•˜๊ธฐ ์œ„ํ•ด, y๋ฅผ ๋Œ€์ฒดํ•˜๋Š” ๋…ธ๋“œ x์— ์—ฌ๋ถ„์˜ black์„ ์ถ”๊ฐ€ํ•ด์ค„ ์ˆ˜ ์žˆ๋‹ค. ์ฆ‰, x๋ฅผ ํฌํ•จํ•˜์—ฌ ๋ฆฌํ”„๊นŒ์ง€์˜ ๊ฒฝ๋กœ์— ํฌํ•จ๋˜๋Š” black์˜ ์ˆ˜๋ฅผ black_count๋ผ๊ณ  ํ•  ๋•Œ, ํ˜„์žฌ x์˜ black parent๊ฐ€ ์‚ญ์ œ๋œ ์ƒํ™ฉ์ด๊ธฐ ๋•Œ๋ฌธ์—, x์˜ black_count๋Š” x์˜ ํ˜•์ œ ๋…ธ๋“œ w์˜ black_count๋ณด๋‹ค 1๋งŒํผ ์ ๋‹ค. ๋”ฐ๋ผ์„œ, x์— ์—ฌ๋ถ„์˜ black์„ ์ถ”๊ฐ€ํ•ด์คŒ์œผ๋กœ์„œ black_count๋ฅผ 1 ์ฆ๊ฐ€์‹œํ‚จ๋‹ค. ์ด๋Ÿฌํ•œ ๋…ธ๋“œ๋ฅผ double black์ด๋ผ๊ณ  ํ•œ๋‹ค. x๋ฅผ double black์œผ๋กœ ํ•˜๋ฉด 5๋ฒˆ ๊ทœ์น™์€ ๋ณต๊ตฌ๋˜์ง€๋งŒ, ๋ชจ๋“  ๋…ธ๋“œ๊ฐ€ red or black์ด์–ด์•ผ ํ•œ๋‹ค๋Š” 1๋ฒˆ ๊ทœ์น™์€ ๊นจ์ง€๊ฒŒ ๋œ๋‹ค.

๐Ÿค” double black์ธ x๋ฅผ resolveํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์€? x์˜ ํ˜•์ œ์ธ w์™€ black_count๋ฅผ ๋™์ผํ•˜๊ฒŒ ๋งž์ถฐ์ฃผ๋Š” ๊ฒƒ์ด๋‹ค. ์ด๋Š” w๋ฅผ red๋กœ ๋งŒ๋“ค๊ฑฐ๋‚˜, x์™€ w์˜ ๋ถ€๋ชจ๋ฅผ ๋‹ค๋ฅด๊ฒŒ ํ•œ ๋’ค x์—๋งŒ black parent๋ฅผ ๋ถ™์—ฌ ์คŒ์œผ๋กœ์„œ ํ•ด์†Œ๋  ์ˆ˜ ์žˆ๊ฒ ๋‹ค.

์ฆ‰, 1๋ฒˆ 2๋ฒˆ 4๋ฒˆ ์†์„ฑ์ด ๊นจ์งˆ ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ, ์‚ญ์ œ๋œ ์ž๋ฆฌ๋ฅผ ์ƒˆ๋กœ ์ฐจ์ง€ํ•˜๊ฒŒ ๋œ ๋…ธ๋“œ x๊ฐ€ red black ์†์„ฑ์„ ์œ„๋ฐ˜ํ•˜์ง€ ์•Š๋„๋ก ์ˆ˜์ •ํ•ด์•ผ ํ•œ๋‹ค. ์ด๋ฅผ rbtree_delete_fixup์ด๋ผ๊ณ  ํ•  ๋•Œ, fixup์˜ ์ผ€์ด์Šค๋Š” ์ด 8๊ฐ€์ง€๋กœ ๋‚˜๋‰œ๋‹ค. ์‚ฝ์ž…๊ณผ ์œ ์‚ฌํ•˜๊ฒŒ, 1-4๋Š” 5-8๊ณผ ๋Œ€์นญ์ด๋‹ค.

if y.color == black
    rbtree_delete_fixup(t, x)

...

rbtree_delete_fixup(rbtree* t, node_t* x)
    while (x != t.root && x.color == BLACK
        if x == x.parent.left
            w = x.parent.right // sibling
            if w.color == RED
                // case 1
               if w.left.color == BLACK && w.right.color == BLACK
                // case 2
            else
                if w.left.color = BLACK
                    // case 3
                else
                    // case 4
        else
            // symmetric to x == x.parent.left (left -> right)
            // case 5 to 8

    x.color = BLACK

๐Ÿค” while๋ฌธ ์•ˆ์—์„œ w๊ฐ€ ํ•ญ์ƒ nil์ด ์•„๋‹˜์„ ๋ณด์ผ ์ˆ˜ ์žˆ๋Š”๊ฐ€?

  1. while๋ฌธ ์ง„์ž…์€ 1. y.color == BLACK 2. x.color == BLACK์„ ๋ณด์žฅํ•œ๋‹ค.
  2. ๋งŒ์•ฝ w == t.nil, y.parent๋กœ๋ถ€ํ„ฐ leaf๊นŒ์ง€ ๊ฐ€๋Š” ๊ฒฝ๋กœ์˜ black height์ด ๊ฐ™์ง€ ์•Š๊ฒŒ ๋œ๋‹ค. (x๊ฐ€ nil์ด๋”๋ผ๋„)
  3. ์ด๋Š” legalํ•œ red black tree์˜ 5๋ฒˆ ์†์„ฑ์„ ์œ„๋ฐ˜ํ•˜๋ฏ€๋กœ, ์‚ญ์ œ ์—ฐ์‚ฐ ์ „ ์ด๋Ÿฌํ•œ ๊ฒฝ์šฐ๋Š” ๋ฐœ์ƒํ•˜์ง€ ์•Š๋Š”๋‹ค.

CASE 0: x์˜ ์ƒ‰์ด RED์ธ ๊ฒฝ์šฐ

x์˜ ์ƒ‰์ด red์ผ ๊ฒฝ์šฐ, while๋ฌธ์— ์ง„์ž…ํ•˜์ง€ ์•Š๊ณ  x.color๋ฅผ black์œผ๋กœ ๋ฐ”๊พธ์–ด ์ค€ ๋‹ค์Œ ์ข…๋ฃŒํ•œ๋‹ค. ์™œ ์ด๊ฒŒ ๊ฐ€๋Šฅํ•œ๊ฐ€? x๊ฐ€ red์ด๊ณ  y์˜ ์ž๋ฆฌ๋ฅผ ๋Œ€์ฒดํ•˜๋ฏ€๋กœ, ์ƒ‰์„ black์œผ๋กœ๋งŒ ๋ฐ”๊ฟ”์ฃผ๋ฉด 5๋ฒˆ ์กฐ๊ฑด์˜ ์œ„๋ฐ˜์„ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค. ๋˜ํ•œ red node๋Š” root๋˜๋Š” leaf๊ฐ€ ๋  ์ˆ˜ ์—†์œผ๋ฏ€๋กœ black์œผ๋กœ ๋ฐ”๊ฟ”์ฃผ์–ด๋„ ์†์„ฑ์„ ์œ„๋ฐ˜ํ•˜์ง€ ์•Š๋Š”๋‹ค. (์ด ๊ฒฝ์šฐ fixup ํ•จ์ˆ˜์— ์ง„์ž…ํ•˜์ž๋งˆ์ž while๋ฌธ์„ ๊ฑด๋„ˆ๋›ฐ๊ณ  x.color = BLACK ๋ผ์ธ๋งŒ ์ˆ˜ํ–‰ํ•œ ํ›„ ์ข…๋ฃŒํ•œ๋‹ค)

๋‚˜๋จธ์ง€ CASE 1-4์—์„œ๋Š” x.color == BLACK์ด๋‹ค. ๋˜, w๋ฅผ x์˜ sibling์œผ๋กœ ์„ค์ •ํ•œ๋‹ค. (x == x.parent.left๋ผ๋ฉด w = x.parent.right)

CASE 1: w์˜ ์ƒ‰์ด BLACK์ธ ๊ฒฝ์šฐ

  • w.color = BLACK
  • x.parent.color = RED
  • rotate_left(t, x.parent)
  • w = x.parent.right

CASE 2-4๋กœ ๊ฐ€๊ธฐ ์œ„ํ•œ ๋‹จ๊ณ„๋ผ๊ณ  ๋ณผ ์ˆ˜ ์žˆ๋‹ค. ๋”ฐ๋ผ์„œ, w.color๋ฅผ black์œผ๋กœ ๋ฐ”๊ฟ”์ฃผ๋˜, ์ด ๊ณผ์ •์—์„œ ์†์„ฑ์„ ๋ณด์กดํ•˜๋Š” ๊ฒƒ์„ ๋ชฉํ‘œ๋กœ ํ•œ๋‹ค. ์ด ๊ฒฝ์šฐ, x๊ฐ€ ๊ฐ€์ง„ double black์€ ํ•ด์†Œํ•˜์ง€ ๋ชปํ•˜๊ณ , ํ•„์—ฐ์ ์œผ๋กœ ๋‹ค๋ฅธ ๋‹จ๊ณ„๋กœ ๊ฐ€๊ฒŒ ๋œ๋‹ค.

CASE 2: w์˜ ์ƒ‰์ด BLACK์ด๊ณ , w์˜ ์ž์‹์ด ๋ชจ๋‘ BLACK์ธ ๊ฒฝ์šฐ

  • w.color = RED
  • x = x.parent

black_count(x) = black_count(w)-1์ด๋ฏ€๋กœ, w.color๋ฅผ red๋กœ ๋งŒ๋“ฆ์œผ๋กœ์„œ double black์„ ํ•ด์†Œํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  x๊ฐ€ ๋‹ค์‹œ x์˜ ๋ถ€๋ชจ๋ฅผ ๊ฐ€๋ฆฌํ‚ค๊ฒŒ ๋งŒ๋“ฆ์œผ๋กœ์„œ while ์กฐ๊ฑด๋ฌธ ๊ฒ€์‚ฌ๋ฅผ ํ•œ๋‹ค. ๋งŒ์•ฝ x.color๊ฐ€ ์—ฌ์ „ํžˆ black์ด๋ผ๋ฉด, w.color๋ฅผ red๋กœ ๋งŒ๋“  ๊ฒƒ์ด 4๋ฒˆ ์†์„ฑ์— ์œ„๋ฐฐ๋˜์ง€ ์•Š๋Š”๋‹ค๊ณ  ํ™•์‹ ํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ x.color๊ฐ€ red๋ผ๋ฉด, while๋ฌธ์— ๋‹ค์‹œ ์ง„์ž…ํ•˜์ง€ ๋ชปํ•˜๊ณ  ๋งˆ์ง€๋ง‰ ๋ผ์ธ์ธ x.color = BLACK์„ ์ˆ˜ํ–‰ํ•จ์œผ๋กœ์„œ 4๋ฒˆ ์†์„ฑ์„ ๋ณด์กดํ•œ๋‹ค.

CASE 3: w์˜ ์ƒ‰์ด BLACK์ด๊ณ , w์˜ ์˜ค๋ฅธ์ชฝ ์ž์‹์ด BLACK์ธ ๊ฒฝ์šฐ

  • w.color = RED
  • w.left = BLACK
  • rotate_right(t, w)
  • w = x.parent.right

CASE 4๋กœ ๊ฐ€๊ธฐ ์œ„ํ•œ ๋‹จ๊ณ„์ด๋‹ค. recoloring & rotation์„ ํ†ตํ•ด w์˜ ์˜ค๋ฅธ์ชฝ ์ž์‹์˜ ์ƒ‰์„ RED๋กœ ๋ฐ”๊ฟ”์ค€๋‹ค.

CASE 4: w์˜ ์ƒ‰์ด BLACK์ด๊ณ , w์˜ ์˜ค๋ฅธ์ชฝ ์ž์‹์ด RED์ธ ๊ฒฝ์šฐ (else)

  • w.color = x.parent.color
  • w.right.color = BLACK
  • x.parent.color = BLACK
  • rotate_left(t, x.parent)
  • x = t.root

์ด ๊ฒฝ์šฐ, ์œ„์™€ ๊ฐ™์€ ์—ฐ์‚ฐ์„ ํ†ตํ•ด x์˜ double black์„ ์ œ๊ฑฐํ•  ์ˆ˜ ์žˆ๋‹ค. (์ฆ‰, CASE 4๋Š” ๋ฌด์กฐ๊ฑด while loop๋ฅผ ์ข…๋ฃŒ์‹œํ‚จ๋‹ค) ์ด๋Š” ์—ฐ์‚ฐ์„ ํ†ตํ•ด x์— black parent๋ฅผ ๋ถ™์—ฌ์คŒ์œผ๋กœ์„œ x์™€ w๊ฐ„์˜ black_count์˜ ๋ถˆ๊ท ํ˜•์„ ํ•ด์†Œํ–ˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.


์ค‘์š”ํ•œ ๊ฒƒ์€ ๊ฒฐ๊ตญ ์‚ฝ์ž…๊ณผ ์‚ญ์ œ๋ฅผ ํ•˜๋ฉด์„œ ๋ ˆ๋“œ ๋ธ”๋ž™ ํŠธ๋ฆฌ์˜ ์†์„ฑ์„ ๋งŒ์กฑ์‹œํ‚ค๋Š” ๊ฒƒ์ด๋‹ค. ๊ทธ๋ž˜์•ผ๋งŒ balanced tree๋ฅผ ์œ„ํ•ด 5๋ฒˆ ์†์„ฑ์„ ๋ณด์กดํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ๋˜ํ•œ, ์ด ๋ชจ๋“  ์—ฐ์‚ฐ์ด ์ตœ๋Œ€ $O(\logN)$์— ์ˆ˜ํ–‰๋จ์ด ์ค‘์š”ํ•˜๋‹ค. insert_fixup์—์„œ๋Š” CASE1, delete_fixup์—์„œ๋Š” CASE2๋งŒ์ด ์œ ์ผํ•˜๊ฒŒ z๊ฐ€ ์ƒ๋‹จ์œผ๋กœ ์˜ฌ๋ผ๊ฐ€๋Š” ๊ฒฝ์šฐ์ด๋‹ค. ๋‚˜๋จธ์ง€๋Š” ๋ชจ๋‘ ์ƒ์ˆ˜๊ฐœ์˜ ๋กœํ…Œ์ด์…˜๊ณผ recoloring๋งŒ์ด ์ˆ˜ํ–‰๋˜๋ฏ€๋กœ, ๋ถ€๋ชจ ๋˜๋Š” ์กฐ๋ถ€ ๋…ธ๋“œ๋กœ ์˜ฌ๋ผ๊ฐ€๋Š” ๊ฒฝ์šฐ์˜ ์‹œ๊ฐ„๋ณต์žก๋„๋งŒ ์ƒ๊ฐํ•  ์ˆ˜ ์žˆ๋‹ค. ์ฆ‰, ํŠธ๋ฆฌ์˜ ๊ท ํ˜•์„ ์œ ์ง€ํ•˜๋Š” ๋น„์šฉ ์ž์ฒด๊ฐ€ (fixup์˜ ์‹œ๊ฐ„๋ณต์žก๋„๊ฐ€) $O(\logN)$์ด๋ฏ€๋กœ ๋ ˆ๋“œ ๋ธ”๋ž™ ํŠธ๋ฆฌ๋ผ๋Š” ์ž๋ฃŒ๊ตฌ์กฐ๊ฐ€ ํšจ์œจ์„ฑ์„ ๋‹ฌ์„ฑํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด๋‹ค.

'DevLog ๐Ÿ“จ > DataStructure' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

[DevLog][DS] Red Black Tree: concept  (0) 2023.09.03