aaTree

RB-Tree๋ฅผ ์‘์šฉํ•œ ํŠธ๋ฆฌ๋กœ RB-Tree์˜ ๋งŽ์€ ์กฐ๊ฑด์„ ์ผ๋ถ€ ์ œ๊ฑฐํ•˜์—ฌ ๊ตฌํ˜„์„ ๋” ๊ฐ„๋‹จํ•˜๊ฒŒ ๋งŒ๋“  ํŠธ๋ฆฌ๋กœ ๊ท ํ˜•์„ ๋งž์ถ”๊ธฐ ์œ„ํ•ด ๋ ˆ๋ฒจ์˜ ๊ฐœ๋…์„ ์‚ฌ์šฉํ•œ ํŠธ๋ฆฌ์ด๋‹ค.

๋ถ€๋ชจ์™€ ๋ ˆ๋ฒจ์ด ๊ฐ™์€ ์ž์‹ ๋…ธ๋“œ์˜ ์—ฐ๊ฒฐ์„ ์ˆ˜ํ‰ ๋งํฌ๋ผ๊ณ  ํ•˜๋ฉฐ, ์ด ๋…ธ๋“œ๋ฅผ ๊ตฌ๋ถ„ํ•˜๊ธฐ ์œ„ํ•ด RED๋ผ๋Š” ๊ฐœ๋…์„ ์ด์šฉํ•œ๋‹ค.

1. ํŠน์ง•

  • ์™ผ์ชฝ ์ž์‹์€ RED๊ฐ€ ๋  ์ˆ˜ ์—†๋‹ค.

  • ์—ฐ์†์œผ๋กœ RED๊ฐ€ ์˜ฌ ์ˆ˜ ์—†๋‹ค. (์ด์ค‘ RED ๋ถˆ๊ฐ€ == ์ด์ค‘ ์ˆ˜ํ‰ ๋งํฌ)

  • ๋ฃจํŠธ์—์„œ null๊ฐ€์ง€ leafnode๊นŒ์ง€์˜ ๊ฒฝ๋กœ์—๋Š” ๋™์ผํ•œ ์ˆ˜์˜ ๋ธ”๋ž™ ๋…ธ๋“œ๊ฐ€ ์กด์žฌํ•œ๋‹ค. (RB Tree์˜ ๊ทœ์น™)

  • ๋ชจ๋“  leaf node์˜ ๋ ˆ๋ฒจ์€ 1์ด๋‹ค

  • ๋ชจ๋“  ์™ผ์ชฝ ์ž์‹์˜ ๋ ˆ๋ฒจ์€ ๋ถ€๋ชจ์˜ ๋ ˆ๋ฒจ๋ณด๋‹ค 1 ๋‚ฎ๋‹ค

  • ๋ชจ๋“  ์˜ค๋ฅธ์ชฝ ์ž์‹์˜ ๋ ˆ๋ฒจ์€ ๋ถ€๋ชจ์™€ ๊ฐ™๊ฑฐ๋‚˜ 1 ๋‚ฎ๋‹ค

  • ๋ชจ๋“  ์˜ค๋ฅธ์ชฝ ์†์ž์˜ ๋ ˆ๋ฒจ์€ ํ• ์•„๋ฒ„์ง€ ๋…ธ๋“œ๋ณด๋‹ค ๋‚ฎ๋‹ค

  • 1๋ณด๋‹ค ํฐ ๋ ˆ๋ฒจ์˜ ๋ชจ๋“  ๋…ธ๋“œ๋“ค์€ 2๊ฐœ์˜ ์ž์‹์„ ๊ฐ–๋Š”๋‹ค

{

}

์™ผ์ชฝ ํŠธ๋ฆฌ๋ฅผ ์–ผํ• ๋ณด๋ฉด RB-Tree๊ฐ™์ง€๋งŒ ์™ผ์ชฝ ์ž์‹์€ RED๋ฅผ ๊ฐ–์ง€ ์•Š๋Š” AA-Tree์ด๊ณ , ์ด๋ฅผ ๋ ˆ๋ฒจ์„ ๊ธฐ์ค€์œผ๋กœ ๋ณด๋ฉด ์˜ค๋ฅธ์ชฝ๊ณผ ๊ฐ™์ด ๊ทธ๋ ค ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

2. ์‚ฌ์šฉ ๊ธฐ๋ฒ•

๐Ÿ“Œ Split

์ด์ค‘ ์ˆ˜ํ‰ ๋งํฌ(์ด์ค‘ red)์ผ ์‹œ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•œ ๋ฐฉ๋ฒ•์œผ๋กœ ์ง€๊ธˆ๊นŒ์ง€ ๋‹ค๋ฅธ BBST์™€ ๋™์ผํ•˜๊ฒŒ rotate์˜ ๊ฐœ๋…์ด๋‹ค.

{

}

์ด์ค‘ red๊ฐ€ ์ƒ๊ธฐ๋Š” ๊ฒฝ์šฐ๋Š” ์œ„ ์‚ฌ์ง„๊ณผ ๊ฐ™์ด ๋ฌด์กฐ๊ฑด ์˜ค๋ฅธ์ชฝ ๋ฐฉํ–ฅ์œผ๋กœ ์ƒ๊ธฐ๊ธฐ ๋•Œ๋ฌธ์— ํ• ์•„๋ฒ„์ง€ ๋…ธ๋“œ(35) ๊ธฐ์ค€์œผ๋กœ left๋ฐฉํ–ฅ์œผ๋กœ๋งŒ rotate์‹œํ‚ค๊ณ  ์ƒ‰์„ ๋ฐ”๊ฟ” ์ฃผ๋ฉด ๋œ๋‹ค.

ํŠน์ง•์œผ๋กœ Split์„ ์ˆ˜ํ–‰ํ•˜๋ฉด level์ด ๋‹ฌ๋ผ์ง„๋‹ค.

๐Ÿ“Œ Skew

red๊ฐ€ ์™ผ์ชฝ์ž์‹์œผ๋กœ ์œ„์น˜ ํ•œ ๊ฒฝ์šฐ ๊ทœ์น™์— ์œ„๋ฐฐ๋˜๊ธฐ ๋•Œ๋ฌธ์— ํ•ด๊ฒฐํ•˜๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ ๋ฌธ์ œ๊ฐ€ ๋˜๋Š” ๋…ธ๋“œ(40)๊ณผ ๋ถ€๋ชจ ๋…ธ๋“œ(50)์„ right rotate ์‹œํ‚ค๊ณ  ์ƒ‰์„ ๋ฐ”๊ฟ” ์ด์ค‘ ๋ ˆ๋“œ๋กœ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค.

{

}

Skew๋Š” ํšŒ์ „์„ ์ˆ˜ํ–‰ํ•ด๋„ ๊ธฐ๋ณธ์ ์œผ๋กœ ๋™์ผํ•œ level์„ ์ƒ์—์„œ ๋ฐ”๋€๋‹ค.

3. ๊ตฌํ˜„

์œ„์—์„œ ๋งํ•œ ๊ฒƒ์ฒ˜๋Ÿผ ์‹ค์ œ ๊ตฌํ˜„์— ์žˆ์–ด, ์‹ค์ œ red / black์˜ ๊ฐ’์„ ๊ฐ–๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์ถ”๊ฐ€ํ•˜์ง€ ์•Š์•„๋„ ๊ตฌํ˜„์ด ๊ฐ€๋Šฅํ•˜๋‹ค. ๋Œ€์‹  level์„ ์ €์žฅํ•  ๋ฐ์ดํ„ฐ๋ฅผ ์ถ”๊ฐ€ํ•ด์•ผ ํ•œ๋‹ค.

๐Ÿ“Œ ์‚ฝ์ž…

BST๊ทœ์น™์— ๋งž๊ฒŒ ์‚ฝ์ž… ํ›„ ๋ฌธ์ œ๊ฐ€ ๋˜๋Š” ๋…ธ๋“œ๋ฅผ Split๊ณผ Skew๋ฅผ ํ†ตํ•ด rebalancingํ•˜๋ฉฐ root๊นŒ์ง€ ์˜ฌ๋ผ๊ฐ€๋ฉด์„œ ๊ทœ์น™์— ์œ„๋ฐฐ๋˜์ง€ ์•Š์„ ๋•Œ ๊นŒ์ง€ split๊ณผ skew๋ฅผ ์ˆ˜ํ–‰ํ•˜๋ฉด ๋œ๋‹ค.

๐Ÿ“Œ ์‚ญ์ œ

1. ์‚ญ์ œํ•  ๋…ธ๋“œ๊ฐ€ red leafnode

๊ทธ๋ƒฅ ์ œ๊ฑฐํ•˜๋ฉด ๋œ๋‹ค.

2. ์‚ญ์ œํ•  ๋…ธ๋“œ๊ฐ€ ํ•˜๋‚˜์˜ leaf node ์ž์‹์„ ๊ฐ–๋Š” ๋‚ด๋ถ€ ๋…ธ๋“œ ์ธ ๊ฒฝ์šฐ

์‚ญ์ œํ•  ๋…ธ๋“œ๋Š” ๊ฒ€์€์ƒ‰์ด๊ณ , ์ž์‹์€ ๋ ˆ๋“œ์ผ ์ˆ˜ ๋ฐ–์— ์—†๊ธฐ ๋•Œ๋ฌธ์— ์ž์‹๊ณผ ๊ฐ’์„ ๊ตํ™˜ ํ›„, ์‚ญ์ œํ•˜๋ฉด ๋œ๋‹ค.

3. ๋‘๊ฐœ์˜ ์ž์‹์ด ์žˆ๊ณ  successor๊ฐ€ red์ผ ๊ฒฝ์šฐ

์ด๋Š” red๊ฐ€ leafnode์ผ ๊ฒฝ์šฐ๋ฐ–์— ์—†๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ’์„ ๊ตํ™˜ ํ›„ leafnode๋ฅผ ์‚ญ์ œํ•˜๋ฉด ๋œ๋‹ค.

4. ๋‘๊ฐœ์˜ ์ž์‹์ด ์žˆ๊ณ  successor๊ฐ€ ํ•œ ๊ฐœ์˜ leaf node ์ž์‹์„ ๊ฐ–๋Š” ๊ฒฝ์šฐ

๊ฐ’์„ ๊ตํ™˜ ํ›„ 2๋ฒˆ ๊ทœ์น™ ์ ์šฉํ•˜๋ฉด ๋œ๋‹ค.

5. ๋‘๊ฐœ์˜ ์ž์‹์ด ์žˆ๊ณ , Successor๊ฐ€ black leaf node ์ด๊ฑฐ๋‚˜ ์‚ญ์ œํ•  ๋…ธ๋“œ๊ฐ€ black leaf node ์ผ ๊ฒฝ์šฐ

black leaf node๋ฅผ ์‚ญ์ œ ์‹œ ๋ ˆ๋ฒจ 2์ด์ƒ์˜ ๋…ธ๋“œ๋Š” 2๊ฐœ์˜ ์ž์‹์„ ๊ฐ–๋Š” ๋‹ค๋Š” ๊ทœ์น™์ด ๊นจ์ง€๋ฏ€๋กœ ์•„๋ž˜์™€ ๊ฐ™์€ ๊ณผ์ •์„ ์ˆ˜ํ–‰ํ•ด์ฃผ์–ด์•ผ ํ•œ๋‹ค.

{

}

Leaf node๋ฅผ ์‚ญ์ œํ•˜๊ณ  ๊ทธ ๋ถ€๋ชจ ๋…ธ๋“œ(15)์˜ ๋ ˆ๋ฒจ์„ ํ•œ ๋‹จ๊ณ„ ๊ฐ์†Œ์‹œํ‚จ๋‹ค.

{

}

ํ• ์•„๋ฒ„์ง€ ๋…ธ๋“œ(30)์˜ ๋ ˆ๋ฒจ๊ณผ ๋ถ€๋ชจ ๋…ธ๋“œ์˜ ๋ ˆ๋ฒจ์ด 2์ด์ƒ ์ฐจ์ด ๋‚œ๋‹ค๋ฉด ํ• ์•„๋ฒ„์ง€ ๋ ˆ๋ฒจ๋„ 1๊ฐ์†Œ์‹œํ‚จ๋‹ค. {

}

๋˜, ํ• ์•„๋ฒ„์ง€ ๋…ธ๋“œ์˜ ์˜ค๋ฅธ์ชฝ ์ž์‹(80)์ด red์ผ ๊ฒฝ์šฐ ์˜ค๋ฅธ์ชฝ ์ž์‹๋„ ๋ ˆ๋ฒจ 1๊ฐ์†Œ ์‹œํ‚จ๋‹ค. {

}

๊ทธ ํ›„, ํ• ์•„๋ฒ„์ง€ ๋…ธ๋“œ(30)๋ฅผ ๊ธฐ์ค€์œผ๋กœ skew, ํ• ์•„๋ฒ„์ง€ ์˜ค๋ฅธ์ชฝ ์ž์‹(80)์˜ ๋…ธ๋“œ ๊ธฐ์ค€์œผ๋กœ skew ํ•œ๋‹ค. {

}

ํ• ์•„๋ฒ„์ง€(30) ์˜ค๋ฅธ์ชฝ ์†์ž ๋…ธ๋“œ(80)๋ฅผ ๊ธฐ์ค€์œผ๋กœ skew๋ฅผ ์ˆ˜ํ–‰ํ•œ๋‹ค.

{

}

๊ทธ ํ›„, ํ• ์•„๋ฒ„์ง€ ๋…ธ๋“œ(30)์„ ๊ธฐ์ค€์œผ๋กœ split์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.

{

}

๋งˆ์ง€๋ง‰์œผ๋กœ ํ• ์•„๋ฒ„์ง€ ๋…ธ๋“œ์˜ ์˜ค๋ฅธ์ชฝ ์ž์‹(60)์„ ๊ธฐ์ค€์œผ๋กœ split์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.

๐Ÿ“Œ ์ˆœํšŒ ๊ณผ์ •

์ผ๋ฐ˜ BST์™€ ๋™์ผํ•˜๊ฒŒ ์ „์œ„ / ์ค‘์œ„ /ํ›„์œ„ ๋กœ ์ˆœํšŒ๋ฅผ ํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ๋‹ค.

๐Ÿ“Œ ํƒ์ƒ‰ ๊ณผ์ •

AA Tree๋˜ํ•œ, BBST์ด๋ฏ€๋กœ ํƒ์ƒ‰ ๋ฐฉ๋ฒ•์€ ๋™์ผํ•˜๊ณ  O(lgn)์˜ ์‹œ๊ฐ„ ๋ณต์žก๋„๋ฅผ ๋ณด์žฅํ•œ๋‹ค.

4. ์‹œ๊ฐ„ ๋ณต์žก๋„

์‚ฝ์ž…๊ณผ ์‚ญ์ œ ๊ณผ์ •์—์„œ rotate๊ฐ€ ์ผ์–ด๋‚˜๋Š”๋ฐ ์ด๋Š” O(1)๋งŒํผ์˜ ์‹œ๊ฐ„์ด ์†Œ์š”๋˜๊ณ  ์ด rotate๊ฐ€ ์ตœ๋Œ€ O(lgn) ๋งŒํผ ์ผ์–ด๋‚˜๊ธฐ ๋•Œ๋ฌธ์— O(lgn)์˜ ์‹œ๊ฐ„ ๋ณต์žก๋„๋ฅผ ๊ฐ–๋Š”๋‹ค.

5. RB Tree์™€ ๋น„๊ต

RB-Tree์™€ ๋น„๊ตํ•ด์„œ ์ž์‹์˜ ์™ผ์ชฝ์— ์žˆ๋ƒ ์˜ค๋ฅธ์ชฝ์— ์žˆ๋ƒ ๋Œ€์นญ์ด์ง€๋„ ์•Š๊ณ  ๋ฌด์กฐ๊ฑด ํ•œ์ชฝ๋ฐฉํ–ฅ์œผ๋กœ๋งŒ ํšŒ์ „๋„ ํ•  ์ˆ˜ ์žˆ๊ณ  case ์ˆ˜๋„ ํ›จ์”ฌ ์ ์–ด ๊ตฌํ˜„์ด ๊ฐ„๋‹จํ•˜๋ฉฐ, red/black์€ ์„ค๋ช…์„ ์‰ฝ๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด ๊ตฌ๋ถ„ ์ง€์–ด ์„ค๋ช…ํ•œ ๊ฒƒ์ด์ง€ ์‹ค์ œ ๊ตฌํ˜„์— ์žˆ์–ด์„œ๋Š” red/black์˜ ๊ฐ’์„ ๊ฐ–๋Š” ์ถ”๊ฐ€ ๋ฐ์ดํ„ฐ๊ฐ€ ํ•„์š”ํ•˜์ง€ ์•Š๋‹ค. (์ž์‹์ด์ง€๋งŒ ๊ฐ™์€ ๋ ˆ๋ฒจ์— ์žˆ๋Š” ์ž์‹์„ red๋ผ๊ณ  ๋ช…๋ช…ํ–ˆ์„ ๋ฟ)

๊ตฌํ˜„ ์ฝ”๋“œ

github์œผ๋กœ ๋ณด๊ธฐ

๐Ÿ“ƒ ๊ตฌํ˜„ ์ฝ”๋“œ (c++) ( ์ ‘๊ธฐ / ํŽผ์น˜๊ธฐ )

/*
 * C++ ์ด์šฉํ•˜์—ฌ AA Tree ๊ตฌํ˜„ํ•˜๊ธฐ
 *
 * ๋ชฉ์  : AA Tree ๊ณต๋ถ€ ํ•˜๊ธฐ ์œ„ํ•ด ์ž‘์„ฑํ–ˆ์œผ๋ฉฐ,
 *       C++ ์ด์šฉํ•˜์—ฌ ์ž‘์„ฑํ•˜์‹œ๋Š” ๋ถ„๋“ค์—๊ฒŒ ๋„์›€์ด ๋˜๊ณ ์ž ํ–ˆ๋‹ค.
 *
 * ์„ค๋ช… : key ๊ฐ’์€ int๋งŒ ๊ฐ€๋Šฅ ํ•˜๋ฉฐ ์ค‘๋ณต key๋Š” ํ—ˆ์šฉ x
 *       ๋‹จ์ˆœ ์—ฐ๊ฒฐ ๋ฆฌ์ŠคํŠธ๋กœ ๊ตฌํ˜„
 *
 *       class AA Tree
 *
 *       ๋ณ€์ˆ˜ :   root => root node
 *
 *       ์ƒ์„ฑ์ž : AATREE =>  root ๋ฅผ null๋กœ ์ดˆ๊ธฐํ™”
 *
 *       ํ•จ์ˆ˜ :   IsKey => key๊ฐ’์ด ์žˆ๋Š”์ง€ ๊ฒ€์‚ฌํ•˜๋Š” ํ•จ์ˆ˜
 *
 *               Insert => ์žฌ๊ท€๋ฅผ ์ด์šฉํ•œ ์‚ฝ์ž… ํ•จ์ˆ˜ (return void)
 *               Delete => ์žฌ๊ท€๋ฅผ ์ด์šฉํ•œ ์‚ญ์ œ ํ•จ์ˆ˜ (return void)
 *
 *               split(x) => x๊ฐ€ ์ด์ค‘ ๋ ˆ๋“œ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค๋ฉด rotate (return void)
 *               skewy(x) => x์˜ ์™ผ์ชฝ์ž์‹์ด ๋ ˆ๋“œ์ผ๋•Œ level๋ณ€ํ™” ์—†์ด ๊ตํ™˜ (return void)
 *
 *               Inorder,Preorder,Postorder => ์ˆœํšŒ ํ•จ์ˆ˜
 *               tree_minimum(x), tree_maximum(x) => ๋…ธ๋“œ x ๊ธฐ์ค€์œผ๋กœ ๊ฐ€์žฅ ์™ผ์ชฝ, ์˜ค๋ฅธ์ชฝ return ํ•จ์ˆ˜
 *
 *               DisplayMenu, SelectMenu => ์ดˆ๊ธฐ MenuํŒ print ํ•จ์ˆ˜
 *               Insert_helper,Delete_helper,order_helper,print_helper => ๊ฐ๊ฐ ์ด๋ฒคํŠธ ์ˆ˜ํ–‰์‹œ ์ž…๋ ฅ๋ฐ›๊ณ  ์กฐ๊ฑด ์—๋Ÿฌ ์ฒ˜๋ฆฌ ์œ„ํ•œ ํ•จ์ˆ˜ ์™€ tree print
 * ํ•ด์ฃผ๋Š” ํ•จ์ˆ˜
 *
 *        Balancing์—์„œ ๊ฐ case์— ๋Œ€ํ•œ ์„ค๋ช…์€ github์— ์ ์–ด ๋†“์•˜๋‹ค.
 *
 * ์ž‘์„ฑ์ž : gowoonsori
 * github : https://github.com/gowoonsori/my-tech/tree/master/dataStructure/Tree
 */

#include <algorithm>  // max() ํ•จ์ˆ˜ ์ด์šฉ
#include <iostream>

struct node {
    int key;
    node *left = nullptr;
    node *right = nullptr;
    int level = 1;
};
typedef node *NodePtr;

class AATree {
   private:
    NodePtr root;  //๋ฃจํŠธ ๋…ธ๋“œ

    // key๊ฐ’์ด ์žˆ๋Š”์ง€ ์—†๋Š”์ง€ ๊ฒ€์‚ฌ ์žˆ์œผ๋ฉด pointer ๊ฐ’, ์—†์œผ๋ฉด nullptr
    NodePtr IsKey(int item) {
        NodePtr t = root;

        /*key๊ฐ’์„ ์ฐพ๊ฑฐ๋‚˜ ์—†๋‹ค๋ฉด break*/
        while (t != nullptr && t->key != item) {
            t = (item < t->key) ? t->left : t->right;
        }
        return t;
    }

    /*์ƒˆ๋กœ์šด key ์‚ฝ์ž…ํ•จ์ˆ˜๋กœ root๋…ธ๋“œ ๋ฐ˜ํ™˜*/
    void Insert(int item, NodePtr &x) {
        /*์ƒˆ๋กœ์šด ๋…ธ๋“œ ์‚ฝ์ž…*/
        if (!x) {
            NodePtr y = new node;
            y->key = item;
            x = y;
            return;
        } else if (x->key < item) {
            Insert(item, x->right);
        } else {
            Insert(item, x->left);
        }

        /*์žฌ๊ท€์ ์œผ๋กœ Insert๋ฅผ ์ˆ˜ํ–‰ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์‚ฝ์ž… ์œ„์น˜๋ถ€ํ„ฐ ๋ฃจํŠธ๊นŒ์ง€ ์˜ฌ๋ผ๊ฐ€๋ฉฐ
          ๊ทœ์น™์ด ์œ„๋ฐฐ๋˜๋Š” ์ง€ ๊ฒ€์‚ฌํ•˜์—ฌ skew, split ์ˆ˜ํ–‰์ด ๊ฐ€๋Šฅํ•˜๋‹ค.*/
        skew(x);
        split(x);
    }

    /*key ์‚ญ์ œ ํ•จ์ˆ˜*/
    void Delete(int item, NodePtr &x) {
        static NodePtr y, p;  // y : ์‚ญ์ œํ•  ๋…ธ๋“œ๊ฐ€ red leaf์ธ์ง€ ํŒ๋ณ„ํ•˜๊ธฐ ์œ„ํ•œ ํฌ์ธํ„ฐ
                              // p : ์ž์‹์ด ๋‘๊ฐœ์ธ ๊ฒฝ์šฐ successor์™€ ๊ฐ’์„ ๊ตํ™˜ํ›„ ์‚ญ์ œํ•˜๊ธฐ ์œ„ํ•œ ํฌ์ธํ„ฐ

        if (!x) return;
        y = x;
        if (item < x->key) {
            Delete(item, x->left);
        } else {
            p = x;
            Delete(item, x->right);
        }

        /*์‚ญ์ œํ•  ๋…ธ๋“œ๊ฐ€ red leaf์ด๊ฑฐ๋‚˜ successor๊ฐ€ red leaf์ผ๋•Œ*/
        if (x == y) {
            p->key = x->key;
            x = x->right;
            delete y;
        } else {
            /*x์˜ ๋ ˆ๋ฒจ๊ณผ ์ž์‹์˜ ๋ ˆ๋ฒจ์ด 2์ด์ƒ ์ฐจ์ด๋‚ ๊ฒฝ์šฐ*/
            if ((x->left && x->left->level < x->level - 1) || (x->right && x->right->level < x->level - 1)) {
                /*x์˜ ๋ ˆ๋ฒจ์„ ๊ฐ์†Œ ์‹œํ‚ค๊ณ  x์˜ ์˜ค๋ฅธ์ชฝ ์ž์‹์ด ๋ ˆ๋“œ ์ผ๊ฒฝ์šฐ ์ž์‹๋„ ๋ ˆ๋ฒจ ๊ฐ์†Œ*/
                if (x->right->level > --x->level) {
                    x->right->level = x->level;
                }
                skew(x);
                skew(x->right);
                skew(x->right);
                split(x);
                split(x);
            }
        }
    }
    void split(NodePtr &x) {
        /*x์˜ ์†์ž์™€ x์˜ ๋ ˆ๋ฒจ์ด ๊ฐ™์„๋•Œ == ์ด์ค‘ ๋ ˆ๋“œ*/
        if (x->right && x->right->right && x->right->right->level == x->level) {
            NodePtr y = x->right;
            x->right = y->left;
            y->left = x;
            x = y;
            x->level++;
        }
    }

    void skew(NodePtr &x) {
        /*x์˜ ์™ผ์ชฝ์ž์‹์ด ๋ ˆ๋“œ์ผ๋•Œ ๋ ˆ๋ฒจ์˜ ๋ณ€ํ™” ์—†์ด ๊ฐ’ ๊ตํ™˜*/
        if (x->left && x->left->level == x->level) {
            NodePtr y = x->left;
            x->left = y->right;
            y->right = x;
            x = y;
        }
    }

    /*y๋ฅผ ์ค‘์‹ฌ์œผ๋กœ ์˜ค๋ฅธ์ชฝ์œผ๋กœ ํšŒ์ „*/

    /*show tree*/
    void print_helper(NodePtr root, std::string indent, bool last) {
        // print the tree structure on the screen
        if (root != nullptr) {
            std::cout << indent;
            if (last) {
                std::cout << "R----";
                indent += "     ";
            } else {
                std::cout << "L----";
                indent += "|    ";
            }

            std::cout << root->key << " (" << root->level << ")" << std::endl;
            print_helper(root->left, indent, false);
            print_helper(root->right, indent, true);
        }
    }

    /*์ค‘์œ„์ˆœํšŒ*/
    void Inorder(NodePtr target) {
        if (target == nullptr) return;
        Inorder(target->left);
        std::cout << target->key << " ";
        Inorder(target->right);
    }
    /*ํ›„์œ„์ˆœํšŒ*/
    void Postorder(NodePtr target) {
        if (target == nullptr) return;
        Postorder(target->left);
        Postorder(target->right);
        std::cout << target->key << " ";
    }
    /*์ „์œ„์ˆœํšŒ*/
    void Preorder(NodePtr target) {
        if (target == nullptr) return;
        std::cout << target->key << " ";
        Preorder(target->left);
        Preorder(target->right);
    }

   public:
    AATree() { this->root = nullptr; }
    //์ตœ์†Ÿ๊ฐ’ ์ฐพ๊ธฐ
    NodePtr tree_minimum(NodePtr x) {
        while (x->left != nullptr) {
            x = x->left;
        }
        return x;
    }
    //์ตœ๋Œ“๊ฐ’ ์ฐพ๊ธฐ
    NodePtr tree_maximum(NodePtr x) {
        while (x->right != nullptr) {
            x = x->right;
        }
        return x;
    }

    void DisplayMenuBoard() {
        std::cout << "         ** AA Tree **     " << std::endl;
        std::cout << "                            " << std::endl;
        std::cout << "              Menu          " << std::endl;
        std::cout << "          1. Insert Key     " << std::endl;
        std::cout << "          2. Delete Key     " << std::endl;
        std::cout << "          3. Show Tree      " << std::endl;
        std::cout << "          4. choose order   " << std::endl;
        std::cout << "          5. show Menu      " << std::endl;
        std::cout << "          6. clear Display  " << std::endl;
        std::cout << "          7. exit           " << std::endl;
        std::cout << std::endl;
    }
    void SelectMenu() {
        DisplayMenuBoard();
        int i = -1;

        while (i != 8) {
            std::cout << "(show Menu : 5) -->  select :   ";
            std::cin >> i;
            switch (i) {
                case 1:
                    Insert_helper();
                    break;
                case 2:
                    Delete_helper();
                    break;
                case 3:
                    print_helper(root, "", true);
                    break;
                case 4:
                    Order_helper();
                    break;
                case 5:
                    DisplayMenuBoard();
                    break;
                case 6:
                    system("cls");
                    DisplayMenuBoard();
                    break;
                case 7:
                    return;
                default:
                    std::cout << " !!! Wrong entered !!!\n" << std::endl;
            }
        }
    }

    void Insert_helper() {
        int item;
        std::cout << "Key to insert  :  ";
        std::cin >> item;
        if (IsKey(item)) {
            std::cout << "!!! " << item << " is already exists !!!\n";
            return;
        }
        Insert(item, root);
        return;
    }

    void Delete_helper() {
        int item;
        std::cout << "Key to delete  :  ";
        std::cin >> item;
        if (!IsKey(item)) {
            std::cout << "!!! " << item << " is not exists !!!\n";
            return;
        }
        Delete(item, root);
        return;
    }

    void Order_helper() {
        int i;
        std::cout << "         == Order Menu ==" << std::endl;
        std::cout << "          1. PreOrder" << std::endl;
        std::cout << "          2. InOrder" << std::endl;
        std::cout << "          3. PostOrder" << std::endl;
        std::cout << "          4. exit" << std::endl;
        std::cout << " --> select  :  ";

        std::cin >> i;
        switch (i) {
            case 1:
                Preorder(this->root);
                std::cout << std::endl;
                break;
            case 2:
                Inorder(this->root);
                std::cout << std::endl;
                break;
            case 3:
                Postorder(this->root);
                std::cout << std::endl;
                break;
            case 4:
                return;
            default:
                std::cout << " !!! Wrong enter !!!\n" << std::endl;
                break;
        }
        return;
    }
};

int main() {
    AATree tree;
    tree.SelectMenu();

    return 0;
}

Last updated