ํฐ์คํ ๋ฆฌ ๋ทฐ
[Swift] ์ฐ๊ฒฐ ๋ฆฌ์คํธ(Linked List)๋ ์งํ์ฒ . (feat. ์ค๊ตญ์ด์ฐจ)
Horang๐ฏ 2024. 3. 1. 17:07์ฐ๊ฒฐ ๋ฆฌ์คํธ๋ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ง๊ณ ์๋ ๋ ธ๋๋ค์ ํฌ์ธํฐ๋ก ์ ํ์ ์ผ๋ก ์ฐ๊ฒฐํด ์ฌ์ฉํ๋ ์๋ฃ ๊ตฌ์กฐ์ ๋๋ค.
๋ ธ๋์๋ ๋ฐ์ดํฐ๋ฅผ ์ํ ์์ฑ(value)์ ๋ค์ ๋ ธ๋์ ์ฃผ์(pointer)๊ฐ ์์ด์ผ ํฉ๋๋ค.
๋ฌด์จ ๋ง์ธ์ง ์ ๋ชจ๋ฅด๊ฒ ๋ค๋ฉด..
์ด ๊ธ์ ์ ๋ชฉ์ฒ๋ผ ์ฐ๊ฒฐ ๋ฆฌ์คํธ๋ ์งํ์ฒ .์ ์๊ฐํ๋ฉด ์ฝ์ต๋๋ค!
(์ค๊ตญ ์ด์ฐจ๋ ๋ค์์ ์ค๋ช ๋๋ฆฌ๊ฒ ์ต๋๋ค.๐)
์งํ์ฒ ์ ์ฌ๋ฌ ๊ฐ์ค๋ค์ด ์ฐ๊ฒฐ๋ ํํ์ ๋๋ค.
๊ฐ์ค์๋ ์น๊ฐ(๋ฐ์ดํฐ)๊ฐ ํ๊ณ ์๊ณ , ๊ฐ ๊ฐ์ค๋ค์ ์ฐ๊ฒฐํ๊ธฐ ์ํด์๋ ์ฐ๊ฒฐ์ (์ฃ์ง, ๋งํฌ)๊ฐ ํ์ํฉ๋๋ค.
๋ค์ ํ๋ฒ, ์งํ์ฒ ์ ๋จธ๋ฆฌ ์์ ๋ ์ฌ๋ฆฌ๋ฉฐ ์ฐ๊ฒฐ ๋ฆฌ์คํธ ์ ์์ ๋ํด ์๊ฐํด๋ณด์์ฃ .
์ฐ๊ฒฐ๋ฆฌ์คํธ๋ ๋ฐ์ดํฐ๋ฅผ ๊ฐ๊ณ ์๋ ๋ ธ๋(= ์งํ์ฒ ๊ฐ์ค)๋ค์ ํฌ์ธํฐ(= ์งํ์ฒ ์ฐ๊ฒฐ์ )์ผ๋ก ์ฐ๊ฒฐํด ์ฌ์ฉํ๋ ์ ํ์ ์๋ฃ ๊ตฌ์กฐ์ ๋๋ค.
์ฐ๊ฒฐ ๋ฆฌ์คํธ์์๋ ๊ฐ์ค์ ๋ ธ๋(node)๋ผ๊ณ ๋ถ๋ฅด๊ณ , ๊ฐ์ค์ ์ฐ๊ฒฐํ๋ ์ฐ๊ฒฐ์ ์ ์ฃ์ง(edge)๋๋ ๋งํฌ(link)๋ผ๊ณ ๋ถ๋ฅธ๋ค๋ ๊ฒ ๋นผ๊ณ ๋ ๋น์ทํ ํํ์ ๊ตฌ์กฐ๋ฅผ ๋๋ ๊ฒ์ ๋๋ค.
์ด์ ์กฐ๊ธ์ ์ฐ๊ฒฐ ๋ฆฌ์คํธ๊ฐ ๋จธ๋ฆฌ ์์์ ์ฐ์์ด ๋์๋์ ?! ๐ค
Singly Liked List๋ ์ค๊ตญ ์ด์ฐจ, Doubly Liked List๋ ์งํ์ฒ .
๊ทธ๋ ๋ค๋ฉด ์ ์ด๋ฒ ํฌ์คํ ์์ '์ค๊ตญ์ด์ฐจ'๋ผ๋ ์ฉ์ด๋ฅผ ์ฌ์ฉํ๊ฒ ๋์๋์ง ์ดํด๋ณด๊ฒ ์ต๋๋ค.
์ฐ๊ฒฐ ๋ฆฌ์คํธ๋ ๋จ์ผ ์ฐ๊ฒฐ ๋ฆฌ์คํธ(Singly Linked List), ์ด์ค ์ฐ๊ฒฐ ๋ฆฌ์คํธ(Doubly Linked List),
์ํ ์ฐ๊ฒฐ ๋ฆฌ์คํธ(Circular Linked List)์ ๊ฐ์ด ๋ค์ํ ์ข ๋ฅ๊ฐ ์์ต๋๋ค.
- ๋จ์ผ ์ฐ๊ฒฐ ๋ฆฌ์คํธ(Singly Linked List): ๊ฐ ๋ ธ๋์ ๋งํฌ๊ฐ ๋ค์ ๋ ธ๋๋ง์ ๊ฐ๋ฆฌํต๋๋ค.
- ์ด์ค ์ฐ๊ฒฐ ๋ฆฌ์คํธ(Doubly Linked List): ๊ฐ ๋ ธ๋์ ๋งํฌ๊ฐ ์์ ๋ ธ๋์ ๋ค์ ๋ ธ๋๋ฅผ ๊ฐ๋ฆฌํต๋๋ค.
- ์ํ ๋ฆฌ์คํธ(Circularly Liked List): ์ฒ์ ๋ ธ๋์ ๋ง์ง๋ง ๋ ธ๋๋ฅผ ์ฐ๊ฒฐํ์ฌ ์ ํ ๊ตฌ์กฐ๊ฐ ์๋ ์ํ ๊ตฌ์กฐ๋ฅผ ๋ง๋ญ๋๋ค.
์ค๊ตญ์ด์ฐจ๋ ์ด์ค ์ฐ๊ฒฐ ๋ฆฌ์คํธ์ ๋จ์ผ ์ฐ๊ฒฐ ๋ฆฌ์คํธ๋ฅผ ๋น๊ตํ๊ธฐ ์ํ ๋น์ ๋ก ์ฌ์ฉ๋์์ต๋๋ค.
(+ ์ํ '์ค๊ตญ์ด์ฐจ'๋ฅผ ๋ชจ๋ฅด์๋ ๋ถ๋ค์ ์ํด ๊ฐ๋ตํ ์ค๋ช ๋๋ฆฌ์๋ฉด, ์ค๊ตญ์ด์ฐจ๋ ์ฌ๋ฌ ๊ฐ์ค๋ก ์ด๋ฃจ์ด์ง ๊ธฐ์ฐจ๋ก,
๊ฐ ๊ฐ์ค์ ์ด์ฉํ ์ ์๋ ๊ณ๊ธ์ด ์กด์ฌํ๋ฉฐ ๊ผฌ๋ฆฌ ์นธ์ ์๋ ์ตํ์ ๊ณ์ธต์ ์๋ถ ์นธ์ผ๋ก ๊ฐ ์ ์๋ ์ด์ฐจ์ ๋๋ค.)
์ด์ค ์ฐ๊ฒฐ ๋ฆฌ์คํธ๋ฅผ ๋ ์ฌ๋ฆด ๋๋ ์งํ์ฒ ์ ์ฐ์ํ๋ฉด ๋๊ณ , ๋จ์ผ ์ฐ๊ฒฐ ๋ฆฌ์คํธ๋ ์ค๊ตญ์ด์ฐจ๋ฅผ ์ฐ์ํ๋ฉด ๋ฉ๋๋ค.
์ค๊ตญ์ด์ฐจ๋ ๋์ ๊ณ์ธต๋ค์ด ์ฌ์ฉํ๋ ๋จธ๋ฆฌ ์นธ์์๋ ํ์ ๊ณ์ธต์ด ์ฌ๋ ๊ผฌ๋ฆฌ ์นธ์ผ๋ก ๊ฐ ์ ์์ง๋ง,
๊ผฌ๋ฆฌ ์นธ์์๋ ๋จธ๋ฆฌ ์นธ์ผ๋ก ๊ฐ ์ ์์ต๋๋ค.
๋ง์ฐฌ๊ฐ์ง๋ก ๋จ์ผ ์ฐ๊ฒฐ ๋ฆฌ์คํธ๋ ํค๋ ๋ ธ๋์์ ํ ์ผ ๋ ธ๋ ๋ฐฉํฅ์ผ๋ก๋ง ๊ฐ ์ ์๊ณ ๊ทธ ๋ฐ๋๋ ๋ถ๊ฐ๋ฅํฉ๋๋ค.
(์ฐ๊ฒฐ ๋ฆฌ์คํธ์ ์ฒซ ๋ ธ๋๋ฅผ ํค๋(Head)๋ ธ๋, ๋ง์ง๋ง ๋ ธ๋๋ฅผ ํ ์ผ(Tail)๋ ธ๋๋ผ๊ณ ๋ถ๋ฆ ๋๋ค.)
๊ทธ๋ฌ๋ ๋ฐ๋๋ก ์๋ฐฉํฅ ์ฐ๊ฒฐ ๋ฆฌ์คํธ๋ฅผ ์งํ์ฒ ๋ก ๋น์ ํ ์ด์ ๋,
์งํ์ฒ ์ ์ด์ฉํ ๊ฒฝํ์ด ์๋ ๋ถ์ด๋ผ๋ฉด ์๊ฒ ์ง๋ง, ํด๋น ์นธ์์๋ ์์ผ๋ก๋ ๊ฐ ์ ์๊ณ ๋ค๋ก๋ ๊ฐ ์ ์์ต๋๋ค.
๋ง์ฐฌ๊ฐ์ง๋ก ์๋ฐฉํฅ ์ฐ๊ฒฐ ๋ฆฌ์คํธ๋ ํด๋น ๋ ธ๋์ ์ ๋ ธ๋์ ๋ค ๋ ธ๋๋ก ์ ๊ทผํ ์ ์์ต๋๋ค.
Array์ Liked List ์ฐจ์ด
์ด์ฏค ๋์ด์ ํ ๊ฐ์ง ๊ถ๊ธ์ฆ์ด ์๊ธธ ์ ์์ต๋๋ค. (์๋๋ฉด ๊ทธ๋ง...๐ )
๋ฐฐ์ด(Array)๊ณผ ์ฐ๊ฒฐ ๋ฆฌ์คํธ(Linked List)์ ์ฐจ์ด๋ ๋ฌด์์ผ๊น์? ๐ง
์ด์ ์ ์๋ฃ๊ตฌ์กฐ์ ๊ดํ ํฌ์คํ ์์ ๋ค๋ค๋ ๋ด์ฉ์ ๋ค์ ์ดํด๋ณด๋ฉด,
์คํ(Stack)๊ณผ ํ(Queue)๋ ๋ฐฐ์ด์ ์ฌ์ฉํ์ฌ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํฉ๋๋ค.
๋ฐฐ์ด์ ์ฌ์ฉํ๋ฉด ๋ฐ์ดํฐ๊ฐ ๋ฉ๋ชจ๋ฆฌ ์์ ์ฐ์์ ์ผ๋ก ์ ์ฅ๋๊ธฐ ๋๋ฌธ์,
์ธ๋ฑ์ค๋ฅผ ํตํด O(1) ์๊ฐ์ ์ํ๋ ๋ฐ์ดํฐ์ ์ ๊ทผํ ์ ์์ต๋๋ค.
๊ทธ๋ฌ๋ ๋ฐฐ์ด์์ ๋งจ ์์ ๋ฐ์ดํฐ๋ฅผ ์ญ์ ํ๋ ๊ฒฝ์ฐ,
ํด๋น ์ธ๋ฑ์ค์ ๋ฐ์ดํฐ ๊ณต๊ฐ์ด ๋น๊ฒ ๋๋ฏ๋ก ๋ค์ ์์นํ ๋ฐ์ดํฐ๋ฅผ ๋ชจ๋ ํ ์นธ์ฉ ์์ผ๋ก ์ด๋์์ผ์ผ ํฉ๋๋ค. (์ค๋ฒ ํค๋)
์ด๋ก ์ธํด O(n)์ ์๊ฐ ๋ณต์ก๋๋ฅผ ๊ฐ์ง๊ฒ ๋ฉ๋๋ค.
(๊ทธ๋์ ๋ฐฐ์ด์ ์ด์ฉํ์ฌ ํ(Queue)๋ฅผ ๊ตฌํํ ๋ ์ค์ ๋ก ๋ฐฐ์ด์ ๋ฐ์ดํฐ๋ฅผ ์ญ์ ํ๋ ๊ฒ์ด ์๋๋ผ,
์ฒซ ๋ฐ์ดํฐ์ ์ธ๋ฑ์ค๋ฅผ ๊ณ์ํด์ ์กฐ์ ํ์ฌ ์ค๋ฒํค๋๋ฅผ ํผํ์ต๋๋ค. ์ดํด๊ฐ ์ด๋ ต๋ค๋ฉด ์ฐธ๊ณ ํด์ฃผ์ธ์.)
๋ฐ๋ฉด, ์ฐ๊ฒฐ ๋ฆฌ์คํธ๋ ๊ฐ ๋ ธ๋๊ฐ ๋ค์ ๋ ธ๋์ ์ฃผ์(๋งํฌ, ์ฃ์ง)๋ฅผ ๊ฐ์ง๊ณ ์์ต๋๋ค.
์ด ๊ตฌ์กฐ๋ ๋ฉ๋ชจ๋ฆฌ ์์ ๋ฐ์ดํฐ(Node)๊ฐ ํฉ์ด์ ธ ์๋ ๊ตฌ์กฐ์
๋๋ค.
๋ฐ๋ผ์ ๋ฐฐ์ด๊ณผ ๋ฌ๋ฆฌ ์ธ๋ฑ์ค๋ฅผ ํตํด ๋ฐ์ดํฐ๋ฅผ ํ์ํ ์ ์์ผ๋ฉฐ, ๋
ธ๋์ ์ ์ฅ๋ ๋ค๋ฅธ ๋
ธ๋์ ์ฃผ์๋ฅผ ๋ฐ๋ผ๊ฐ์ผ ํฉ๋๋ค.
๋ฐ๋ผ์ ๋งจ ์์ ๋ฐ์ดํฐ๋ฅผ ์ญ์ ํด๋ ์ค๋ฒํค๋๊ฐ ๋ฐ์ํ์ง ์์ O(1)์ ์๊ฐ ๋ณต์ก๋๋ฅผ ๊ฐ์ง๋๋ค.
๊ทธ๋ฌ๋ ์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํ์ฌ ๋น ๋ฅด๊ฒ ๋ฐ์ดํฐ์ ์ ๊ทผํ ์ ์๊ธฐ ๋๋ฌธ์ ๋ฐ์ดํฐ๋ฅผ ํ์ํ๋ ๋ฐ ์๊ฐ์ด ์ค๋ ๊ฑธ๋ฆด ์ ์์ต๋๋ค. ๊ฐ ๋ ธ๋๋ฅผ ์์ฐจ์ ์ผ๋ก ๋ฐ๋ผ๊ฐ์ผ ํ๋ฏ๋ก ์๊ฐ ๋ณต์ก๋๋ O(n)์ด ๋ฉ๋๋ค.
์์ฝํ์๋ฉด,
๋ฐฐ์ด์ ๋ฐ์ดํฐ๊ฐ ์ฐ์์ ์ผ๋ก ์ ์ฅ๋์ด ์์ด ์ธ๋ฑ์ค๋ฅผ ํตํ ๋น ๋ฅธ ์ ๊ทผ์ด ๊ฐ๋ฅํ์ง๋ง,
์ญ์ ์์๋ ์ค๋ฒํค๋๊ฐ ๋ฐ์ํ์ฌ ์๊ฐ์ด ์ค๋ ๊ฑธ๋ฆด ์ ์์ต๋๋ค.
๋ฐ๋ฉด์ ์ฐ๊ฒฐ ๋ฆฌ์คํธ๋ ๋ฐ์ดํฐ๊ฐ ํฉ์ด์ ธ ์์ด ์ธ๋ฑ์ค๋ฅผ ํ์ฉํ์ง ๋ชปํ๋ฉฐ,
์ญ์ ์์๋ ํด๋น ๋ฐ์ดํฐ๋ฅผ ๊ฐ๋ ๋ ธ๋๋ง ์ ๊ฑฐํ๋ฉด ๋๊ธฐ ๋๋ฌธ์ ๋น ๋ฅด๊ฒ ์ฒ๋ฆฌํ ์ ์์ต๋๋ค.
๋ฉ๋ชจ๋ฆฌ ์ ์ฅ์ ๊ด๋ จํ์ฌ ๋ ์๊ณ ์ถ๋ค๋ฉด ์๋ ๊ธ์ ์ฐธ๊ณ ํด์ฃผ์ธ์.๐
Singly Liked List์ Doubly Liked List ์ฐจ์ด
๋๋ฌด ๊ธธ์ด์ง๊น๋ด ์๋ตํ๋ ค๊ณ ํ๋๋ฐ, ์ ์ ๋ง์กฑ๋๋ฅผ ๋์ด๊ณ ์ถ์ด ์ถ๊ฐํด๋ณด๊ฒ ์ต๋๋ค.๐
์๋ฐฉํฅ ์ฐ๊ฒฐ ๋ฆฌ์คํธ์ ๋จ์ผ ์ฐ๊ฒฐ ๋ฆฌ์คํธ์ ์ฐจ์ด๋ฅผ ๊ฐ๋จํ๊ฒ ์๊ฐํด๋ด ์๋ค.
์๋ฐฉํฅ ์ฐ๊ฒฐ ๋ฆฌ์คํธ๋ ๊ฐ ๋ ธ๋๊ฐ ์ด์ ๋ ธ๋์ ์ฃ์ง๋ฅผ ํจ๊ป ๊ฐ๊ณ ์๊ธฐ ๋๋ฌธ์,
๋จ์ผ ์ฐ๊ฒฐ ๋ฆฌ์คํธ๋ณด๋ค ๋ ๋น ๋ฅธ ์๊ฐ์ ํ์์ ํ ์ ์์ต๋๋ค.
์๋ฅผ ๋ค์ด 100๊ฐ์ ๋ ธ๋๊ฐ ์ ์ฅ๋ ์ฐ๊ฒฐ ๋ฆฌ์คํธ์ธ๋ฐ
๋จ์ผ ์ฐ๊ฒฐ ๋ฆฌ์คํธ์ ๊ฒฝ์ฐ 99๋ฒ์งธ ๋ ธ๋๋ฅผ ์ฐพ๊ธฐ ์ํด์๋ ์ฒซ ๋ฒ์งธ ๋ ธ๋๋ถํฐ 99๋ฒ์ ํ์์ ํด์ผํ์ง๋ง,
์๋ฐฉํฅ์ ๊ฒฝ์ฐ๋ ๋ค์์๋ถํฐ์ธ 100๋ฒ์งธ ๋ ธ๋๋ถํฐ ํ์์ ํ์ฌ ๋จ 2๋ฒ๋ง์ 99๋ฒ์งธ ๋ ธ๋๋ฅผ ์ฐพ์ ์ ์๊ฒ ๋ฉ๋๋ค.
์์ ์์๋ง ๋ณด๋ฉด ๋ฌด์กฐ๊ฑด ์๋ฐฉํฅ ์ฐ๊ฒฐ ๋ฆฌ์คํธ๊ฐ ๋ ์ข์๋ณด์ด์ง๋ง, ์๋ฐฉํฅ ์ฐ๊ฒฐ ๋ฆฌ์คํธ๋ ๋จ์ ์ด ์์ต๋๋ค.
๊ฐ ๋ ธ๋๊ฐ ์์ ๋ ธ๋์ ๋งํฌ๋ง ์ ์ฅํ๋ ๊ฒ์ด ์๋ ์ด์ ๋ ธ๋์ ๋งํฌ๋ ์ ์ฅํด์ผ ํ๊ธฐ ๋๋ฌธ์,
๊ทธ๋งํผ ๋ฉ๋ชจ๋ฆฌ ์๋ชจ๊ฐ ๋ ํฌ๊ธฐ ๋๋ฌธ์ ๊ณต๊ฐ ๋ณต์ก๋๊ฐ ์๋์ ์ผ๋ก ์ข์ง ์์ต๋๋ค.
๋ฐ๋ผ์ ์ฐ๊ฒฐ ๋ฆฌ์คํธ๋ฅผ ์ฌ์ฉํด์ผ ํ๋ ์ํฉ์์๋ ๋ฌธ์ ์ํฉ์ ๋ง๊ฒ ๋จ์ผ ์ฐ๊ฒฐ๊ณผ ์๋ฐฉํฅ ์ค ๋ ์๋ง์ ์๋ฃ๊ตฌ์กฐ๋ฅผ ์ ํํ ์ ์์ด์ผ ํฉ๋๋ค.
Swift๋ก Doubly Liked List ๊ตฌํ
์ด์ ์ง์ ์ฐ๊ฒฐ ๋ฆฌ์คํธ๋ฅผ ๊ตฌํํด๋ณด๊ฒ ์ต๋๋ค.
์๋ฐฉํฅ ์ฐ๊ฒฐ ๋ฆฌ์คํธ๋ฅผ ์ํ์ผ๋ก ์ฐ๊ฒฐ๋ ์ํ ๋ฆฌ์คํธ๋ก ์์ฑํ๊ฒ ์ต๋๋ค.
์ด๋, ๊ธฐ์ค ๋ ธ๋ ์ญํ ์ ํ๋ dummy ๋ ธ๋๋ฅผ ์ฌ์ฉํ์ฌ ๋ฉ์๋๋ค์ ์ฝ๊ฒ ๊ตฌํํ๊ฒ ์ต๋๋ค.
(dummy node์ dat๋ nil๋ก ์ง์ ํ๊ณ , dummy node๊ฐ ์ฐ๊ฒฐ ๋ฆฌ์คํธ์ head ๋ ธ๋๋ก ์ฌ์ฉํฉ๋๋ค.)
์๋ฐฉํฅ ์ฐ๊ฒฐ ๋ฆฌ์คํธ๋ฅผ ์์ฑํ๋ ๊ฒ์ ์ตํ๋ค๋ฉด, ๋จ์ผ ์ฐ๊ฒฐ ๋ฆฌ์คํธ๋ ๋น๊ต์ ์ฝ๊ฒ ๊ตฌํํ ์ ์์ ๊ฒ์ ๋๋ค!
(๋จ์ผ ์ฐ๊ฒฐ ๋ฆฌ์คํธ์์๋ ํค๋ ๋ ธ๋๋ฅผ ๋๋ฏธ๋ก ์ฌ์ฉํ ํ์ ์์ต๋๋ค!)
Node ์์ฑ
// Doubly Linked List Node
class DoublyLinkedListNode<T: Equatable>: Equatable {
static func == (lhs: DoublyLinkedListNode<T>, rhs: DoublyLinkedListNode<T>) -> Bool {
return lhs === rhs
}
let data: T?
var next: DoublyLinkedListNode?
weak var previous: DoublyLinkedListNode?
init(data: T?) {
self.data = data
self.next = self
self.previous = self
}
}
(๋์ค์ ์ฌ์ฌ์ฉ์ ์ํด ์ ๋ค๋ฆญ์ผ๋ก ์ ์ธํด์ฃผ์์ง๋ง, ์ฝํ ๋ฌธ์ ์ ๋ฐ๋ผ ์ฝ๊ฐ์ฉ ๋ฌ๋ผ์ง๋ ๊ฒ๋ค์ด ์์ด์ ์ด๋ค ์์ผ๋ก ๊ตฌํํ๋์ง๋ง ๋ณด๋ฉด ๋ ๊ฑฐ ๊ฐ์์!)
๋จ์ผ ์ฐ๊ฒฐ ๋ฆฌ์คํธ์๋ ๋ฌ๋ฆฌ ์๋ฐฉํฅ ์ฐ๊ฒฐ ๋ฆฌ์คํธ ๋ ธ๋๋ ์ด์ ๋ ธ๋์ ๋งํฌ๋ ์ ์ฅํด์ผํ๊ธฐ ๋๋ฌธ์
next์ previous ํ๋กํผํฐ๋ฅผ ์ ์ธํด์ค๋๋ค.
์ ๋ค๋ฆญ์ผ๋ก ์ ์ธํด์คฌ๊ธฐ ๋๋ฌธ์ ๋์ค์ ๋น๊ต๋ฅผ ์ํด Equatable ํ๋กํ ์ฝ์ ์ฑํํด์ค๋๋ค.
๋น๊ต๋ ์ฐธ์กฐํ๊ณ ์๋ ์ธ์คํด์ค๊ฐ ๊ฐ์์ง๋ฅผ ํ์ธํด์ฃผ๊ธฐ ์ํด '===' ๋ฅผ ์ฌ์ฉํด์ค๋๋ค.
์ฐ๊ฒฐ ๋ฆฌ์คํธ ๊ตฌ์กฐ์ฒด ์์ฑ
struct DoublyLinkedList<T: Equatable> {
typealias Node = DoublyLinkedListNode<T>
private var head = Node(data: nil) // head๋ฅผ dummy ๋
ธ๋๋ก ์์ฑ
public var isEmpty: Bool {
return head.next?.data == nil
}
public var first: Node? {
return head.next
}
}
ํ์ํ ๋ฉ์๋๋ค์ ๊ตฌํํ๊ธฐ ์ , ๊ฐ๋จํ๊ฒ ํ์ํ ํ๋กํผํฐ๋ค์ ์ ์ธํด ๋ณด๊ฒ ์ต๋๋ค.
(์ฝ๋ ๊ตฌํ๋ถ๊ฐ ๊ธธ์ด์ง๋ ๊ฒ์ ๋ง๊ธฐ ์ํด typealias ๋ฌธ๋ฒ์ ์ฌ์ฉํ์์ต๋๋ค.)
์ฐ๊ฒฐ ๋ฆฌ์คํธ๊ฐ ๋น์ด์๋์ง ํ์ธ์ ์ํ isEmpty์ ์ฒซ ๋ ธ๋๋ฅผ ๋ฆฌํดํด์ฃผ๋ first ํ๋กํผํฐ๋ฅผ ๊ตฌํํด์ฃผ์์ต๋๋ค.
head ๋ ธ๋์ ๊ฒฝ์ฐ ์์์ ์ค๋ช ํ๋ ๊ฒ์ฒ๋ผ nil์ ๊ฐ๋ ๋๋ฏธ ๋ ธ๋๋ก ์์ฑ์ ํด์ฃผ์์ต๋๋ค.
โญ๏ธsplice ๋ฉ์๋: ์๋ผ๋ธ ํ ์ด๋ํ๊ธฐ ์ฐ์ฐ O(1)
์ฝ๋ ์์ฑ ์ ๊ฐ์ฅ ์ค์ํ ๊ตฌํ๋ถ์ ๋๋ค.
์๋ฐฉํฅ ์ฐ๊ฒฐ ๋ฆฌ์คํธ์์ ํ์ํ ๋ฉ์๋์ ๊ตฌํ์ ์ฝ๊ฒ ํด์ฃผ๊ธฐ ์ํด splice ์ฐ์ฐ์ ์ฌ์ฉํด์ค๋๋ค.
splice(a, b, x) ์ฐ์ฐ์ ์๋ฐฉํฅ ์ฐ๊ฒฐ ๋ฆฌ์คํธ์์ ๋ ธ๋ a์ ๋ ธ๋ b์ฌ์ด์ ๋ ธ๋๋ค์ ์๋ผ๋ด์ ๋ ธ๋ x ๋ค์ ๋ถ์ด๋ ์ฐ์ฐ์ ๋ปํฉ๋๋ค.
์ด ์ฐ์ฐ์ ์ฌ์ฉํ๊ธฐ ์ํด์๋ ํ์์ ์ธ ์กฐ๊ฑด 3๊ฐ์ง๊ฐ ์์ต๋๋ค.
- ์กฐ๊ฑด 1: a ๋ ธ๋ ๋ค์์ b ๋ ธ๋๊ฐ ์กด์ฌํฉ๋๋ค. (๋ฐ๋ก ์์ด ์๋์ด๋ ์๊ด์์)
- ์กฐ๊ฑด 2: a ๋ ธ๋์ b ๋ ธ๋ ์ฌ์ด์ head(๋๋ฏธ) ๋ ธ๋๊ฐ ์กด์ฌํ์ง ์์ต๋๋ค.
- ์กฐ๊ฑด 3: a ๋ ธ๋์ b ๋ ธ๋ ์ฌ์ด์ x ๋ ธ๋๊ฐ ์กด์ฌํ์ง ์์ต๋๋ค.
func splice(a: Node, b: Node, x: Node) {
guard let aPrevious = a.previous, let bNext = b.next, let xNext = x.next else { return }
// [a..b] ๊ตฌ๊ฐ์ ์๋ผ๋ด๊ธฐ
aPrevious.next = bNext
bNext.previous = aPrevious
// [a..b]๋ฅผ x ๋ค์์ ์ฝ์
ํ๊ธฐ
x.next = a
a.previous = x
b.next = xNext
xNext.previous = b
}
moveAfter, moveBefore: splice๋ฅผ ์ด์ฉํ์ฌ ์ด๋ ํจ์ ์ ์ O(1)
moveAfter(a: Node, x: Node)๋ ๋ ธ๋ a๋ฅผ x ๋ค์์ผ๋ก ์ด๋์ํค๋ ๋ฉ์๋์ด๋ฉฐ, splice ๋ฉ์๋๋ฅผ ํธ์ถํ์ฌ ์์ ์๊ฐ์ด ๊ฑธ๋ฆฝ๋๋ค.
๋ง์ฐฌ๊ฐ์ง๋ก, moveBefore(a: Node, x: Node)๋ ๋ ธ๋ a๋ฅผ x ์ด์ ์ผ๋ก ์ด๋์ํค๋ ๋ฉ์๋์ด๋ฉฐ, splice ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ์์ ์๊ฐ์ด ๊ฑธ๋ฆฝ๋๋ค.
// moveAfter ๋ฉ์๋
func moveAfter(a: Node, x: Node) { // ๋
ธ๋ a๋ฅผ x ๋ค์์ผ๋ก ์ด๋
self.splice(a: a, b: a, x: x)
}
// moveBefore ๋ฉ์๋
func moveBefore(a: Node, x: Node) { // ๋
ธ๋ a๋ฅผ x ์ด์ ์ผ๋ก ์ด๋
guard let xPrevious = x.previous else { return }
self.splice(a: a, b: a, x: xPrevious)
}
insertAfter, insertBefore: splice๋ฅผ ์ด์ฉํ์ฌ ์ฝ์ ํจ์ ์ ์ O(1)
insertAfter(data: T, x: Node)๋ data ๊ฐ์ ๊ฐ๋ ์ ๋ ธ๋๋ฅผ ๋ง๋ค์ด ๋ ธ๋ x ๋ค์ ์ฝ์ ํ๋ ๋ฉ์๋์ด๋ฉฐ, moveAfter ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ์์๊ฐ์ด ๊ฑธ๋ฆฝ๋๋ค.
๋ง์ฐฌ๊ฐ์ง๋ก, insertBefore(data: T, x: Node)๋ data ๊ฐ์ ๊ฐ๋ ์ ๋ ธ๋๋ฅผ ๋ง๋ค์ด ๋ ธ๋ x ์์ ์ฝ์ ํ๋ ๋ฉ์๋์ด๋ฉฐ, moveBefore ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ์์์๊ฐ์ด ๊ฑธ๋ฆฝ๋๋ค.
// insertAfter ๋ฉ์๋
func insertAfter(data: T, x: Node) {
moveAfter(a: Node(data: data), x: x)
}
// insertBefore ๋ฉ์๋
func insertBefore(data: T, x: Node) {
moveBefore(a: Node(data: data), x: x)
}
append, appendFirst: splice๋ฅผ ์ด์ฉํ์ฌ ์ฝ์ ํจ์ ์ ์ O(1)
append(data: T)๋ data ๊ฐ์ ๊ฐ๋ ์ ๋ ธ๋๋ฅผ ๋ง๋ค์ด ์ ์ผ ๋ค์ ์ฝ์ ํ๋ ๋ฉ์๋์ด๋ฉฐ, insertBefore ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ์์ ์๊ฐ์ด ๊ฑธ๋ฆฝ๋๋ค.
๋ง์ฐฌ๊ฐ์ง๋ก, appendFirst(data: T)๋ data ๊ฐ์ ๊ฐ๋ ์ ๋ ธ๋๋ฅผ ๋ง๋ค์ด ์ ์ผ ์์ ์ฝ์ ํ๋ ๋ฉ์๋์ด๋ฉฐ, insertAfter ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ์์ ์๊ฐ์ด ๊ฑธ๋ฆฝ๋๋ค.
๋ ๋ฉ์๋๋ head ๋ ธ๋์ ์, ๋ค๋ก ์๋ก์ด ๋ ธ๋๋ฅผ ์ถ๊ฐํ๋ ๋ ธ๋๋ก ํค๋ ๋ ธ๋๋ฅผ ์ฐธ์กฐํ์ฌ ๊ธฐ๋ฅ์ ๊ตฌํํด์ฃผ๋ฉด ๋ฉ๋๋ค.
// append ๋ฉ์๋
func append(data: T) {
insertBefore(data: data, x: head)
// insertBefore(data: data, x: head)๊ณผ ๊ฐ์ ๊ธฐ๋ฅ
// guard let headPrev = head.previous else { return }
// let newNode = Node(data: data)
// self.splice(a: newNode, b: newNode, x: headPrev)
}
// appendFirst ๋ฉ์๋
func appendFirst(data: T) {
insertAfter(data: data, x: head)
// insertAfter(data: data, x: head)๊ณผ ๊ฐ์ ๊ธฐ๋ฅ
// let newNode = Node(data: data)
// self.splice(a: newNode, b: newNode, x: head)
}
remove: ์ญ์ ํจ์ O(1)
remove(x: Node)๋ x ๋
ธ๋๋ฅผ ์ญ์ ํ๋ ๋ฉ์๋์ด๋ฉฐ, x์ ์ด์ ๋ฐ ๋ค์ ๋
ธ๋๋ค์ ๋ํ ์ฐธ์กฐ๋ฅผ ๊ฐฑ์ ํ๋ฏ๋ก ์์ ์๊ฐ์ด ๊ฑธ๋ฆฝ๋๋ค. (๋จ, x๋ head ๋
ธ๋๊ฐ ์๋์ด์ผ ํฉ๋๋ค.)
// remove ๋ฉ์๋
func remove(x: Node) -> Node? {
if x == head {
return nil
}
x.next?.previous = x.previous
x.previous?.next = x.next
return x
}
search: ํ์ ํจ์ O(n)
search(data: T)๋ x ๋ ธ๋๋ฅผ ํ์ํ๋ ๋ฉ์๋์ด๋ฉฐ, ๋ฆฌ์คํธ๋ฅผ ์ํํ์ฌ ๋ฐ์ดํฐ๋ฅผ ์ฐพ์๊ฐ๋ฏ๋ก ์ต์ ์ ๊ฒฝ์ฐ ๋ฆฌ์คํธ์ ๊ธธ์ด์ ๋น๋กํ๋ ์ ํ ์๊ฐ ์์๋ฉ๋๋ค.
// search ๋ฉ์๋
func search(data: T) -> Node? {
var node = head.next
while node != head {
if node?.data == data {
return node
}
node = node?.next
}
return nil
}
printList: ์ถ๋ ฅ ํจ์ O(n)
printList()๋ ๋ชจ๋ ๋ ธ๋์ ๋ฐ์ดํฐ๋ฅผ ์ถ๋ ฅํ๋ ๋ฉ์๋์ด๋ฉฐ, ๋ฆฌ์คํธ๋ฅผ ์ํํ์ฌ ๊ฐ ๋ ธ๋์ ๋ฐ์ดํฐ๋ฅผ ์ถ๋ ฅํ๋ฏ๋ก ์ต์ ์ ๊ฒฝ์ฐ ๋ฆฌ์คํธ์ ๊ธธ์ด์ ๋น๋กํ๋ ์ ํ ์๊ฐ ์์๋ฉ๋๋ค.
์ด ๋ฉ์๋๋ ๊ตณ์ด ์์ฑํ์ง ์์๋ ๋๋ฉฐ, ์ ๊ตฌํ์ด ๋์๋์ง ํ์ธํ๋ ๋ฉ์๋์ ๋๋ค.
// printList ๋ฉ์๋
func printList() {
var current = head.next
while let data = current?.data {
print("\(data) -> ", terminator: "")
current = current?.next
}
print("nil")
}
์ ์ฒด ์ฝ๋
// Node ์ ์ธ
class DoublyLinkedListNode<T: Equatable>: Equatable {
static func == (lhs: DoublyLinkedListNode<T>, rhs: DoublyLinkedListNode<T>) -> Bool {
return lhs === rhs
}
let data: T?
var next: DoublyLinkedListNode?
weak var previous: DoublyLinkedListNode?
init(data: T?) {
self.data = data
self.next = self
self.previous = self
}
}
// ์๋ฃ ๊ตฌ์กฐ ์ ์ธ
struct DoublyLinkedList<T: Equatable> {
typealias Node = DoublyLinkedListNode<T>
private var head = Node(data: nil)
public var isEmpty: Bool {
return head.next?.data == nil
}
public var first: Node? {
return head.next
}
// splice ๋ฉ์๋์ ์๊ฐ ๋ณต์ก๋: O(1)
func splice(a: Node, b: Node, x: Node) {
guard let aPrevious = a.previous, let bNext = b.next, let xNext = x.next else { return }
aPrevious.next = bNext
bNext.previous = aPrevious
x.next = a
a.previous = x
b.next = xNext
xNext.previous = b
}
// append ๋ฉ์๋์ ์๊ฐ ๋ณต์ก๋: O(1)
func append(data: T) {
insertBefore(data: data, x: head)
}
// appendFirst ๋ฉ์๋์ ์๊ฐ ๋ณต์ก๋: O(1)
func appendFirst(data: T) {
insertAfter(data: data, x: head)
}
// insertAfter ๋ฉ์๋์ ์๊ฐ ๋ณต์ก๋: O(1)
func insertAfter(data: T, x: Node) {
moveAfter(a: Node(data: data), x: x)
}
// insertBefore ๋ฉ์๋์ ์๊ฐ ๋ณต์ก๋: O(1)
func insertBefore(data: T, x: Node) {
moveBefore(a: Node(data: data), x: x)
}
// moveAfter ๋ฉ์๋์ ์๊ฐ ๋ณต์ก๋: O(1)
func moveAfter(a: Node, x: Node) {
self.splice(a: a, b: a, x: x)
}
// moveBefore ๋ฉ์๋์ ์๊ฐ ๋ณต์ก๋: O(1)
func moveBefore(a: Node, x: Node) {
guard let xPrevious = x.previous else { return }
self.splice(a: a, b: a, x: xPrevious)
}
// search ๋ฉ์๋์ ์๊ฐ ๋ณต์ก๋: O(n)
func search(data: T) -> Node? {
var node = head.next
while node != head {
if node?.data == data {
return node
}
node = node?.next
}
return nil
}
// remove ๋ฉ์๋์ ์๊ฐ ๋ณต์ก๋: O(1)
func remove(x: Node) -> Node? {
if x == head {
return nil
}
x.next?.previous = x.previous
x.previous?.next = x.next
return x
}
// printList ๋ฉ์๋์ ์๊ฐ ๋ณต์ก๋: O(n)
func printList() {
var current = head.next
while let data = current?.data {
print("\(data) -> ", terminator: "")
current = current?.next
}
print("nil")
}
}
๋ง๋ฌด๋ฆฌ
์๊ฐ๋ณด๋ค ๊ธฐ๋กํ๊ณ ์ ํ๋ ๋ด์ฉ๋ค์ด ๋ง์์ ธ ๊ธ์ด ๊ฝค ๊ธธ์ด์ง ๊ฒ ๊ฐ๋ค์. ๐
๊ทธ๋๋ ์ด๋ ๊ฒ ๋ชจ๋ ๋ด์ฉ์ ๋ค๋ค์ ๊ทธ๋ฐ์ง ์ ๋จธ๋ฆฌ ์์๋ ๋ ์ ๊ธฐ์ต๋๋ ๊ฒ ๊ฐ์ต๋๋ค.
(์ด ๊ธ์ ์ฝ๋ ๋ถ๋ค๋ ๊ทธ๋ฌ์ผ๋ฉด ์ข๊ฒ ์ต๋๋ค!)
๋ชจ๋ ์๋ฃ ๊ตฌ์กฐ์ ๋ํ ํผ๋๋ฅผ ์ฌ๋ฆฌ๊ณ ์ถ์ง๋ง,
์ด๊ฒ์ ๊ฒ ํ๊ณ ์ถ์ ๊ฒ๋ค์ด ๋๋ฌด ๋ง์ ๊ณ์ํด์ ํ์์๊ฐ ๋๋ค๊ฐ ์ด์ ์์ผ ์ฐ๊ฒฐ ๋ฆฌ์คํธ์ ๊ดํด ์์ฑ์ ํด๋ณด์์ต๋๋ค.
์์ผ๋ก ๊ธฐ๋กํ ์๋ฃ๊ตฌ์กฐ๋ค์ด ๋ง์ง๋ง ๋น ๋ฅธ ์์ผ ๋ด์ ๋ค ์์ฑํด๋ณด๊ฒ ์ต๋๋ค!
๋ง์ง๋ง์ผ๋ก ์ฝ๋ฉ ํ ์คํธ ๋ฌธ์ ๋ฅผ ํ๋ฉด์ ์๊ฒ๋ ์ฌ์ค์ธ๋ฐ
์ฐ๊ฒฐ ๋ฆฌ์คํธ๋ ํ ์คํธ ์๋ํฐ์์ ๋ง์ด ์ฌ์ฉ๋๋ ์๋ฃ๊ตฌ์กฐ๋ผ๊ณ ํฉ๋๋ค.
์๋ํฐ์ ์ปค์๋ฅผ ๊ณ์ํด์ ์ ์ฅํ๊ณ ์๋ค๋ฉด ์ฐ๊ฒฐ ๋ฆฌ์คํธ์ ๋จ์ ์ธ ํ์ ๊ณผ์ ์ด ํ์๊ฐ ์์ด์ง๊ณ ,
๋น ๋ฅธ ์๊ฐ์ ์์ ์ด ์ํ๋ ๊ธ์(์ปค์)๋ฅผ ์ญ์ ๋๋ ์ฝ์ ์ ์งํํ ์ ์๊ธฐ ๋๋ฌธ์ ๋๋ค.
์ด์์ผ๋ก ์ฐ๊ฒฐ ๋ฆฌ์คํธ ํฌ์คํ ์ ๋ง์น๊ฒ ์ต๋๋ค!!
์๋ชป๋ ๋ด์ฉ์ด๋ ๊ถ๊ธํ์ ์ ์ด ์๋ค๋ฉด ๋๊ธ ๋จ๊ฒจ์ฃผ์ธ์. ๐ค
์ฝ์ด์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค.
๐ ์ฐธ๊ณ ์๋ฃ
ํ๊ตญ์ธ๋ ์ ์ฐฌ์ ๊ต์๋์ Data Structures with Python ๊ฐ์
์ํค ๋ฐฑ๊ณผ: ์ฐ๊ฒฐ ๋ฆฌ์คํธ
'Computer > Data Structure' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
ํด์ ํ ์ด๋ธ(Hash Table)์ ๋์๊ด. (5) | 2024.03.08 |
---|---|
[Swift] ํ(Queue)๋ ์ ์ฐฉ์. (1) | 2024.01.25 |
[Swift] ์คํ(Stack)์ ํ๋ง๊ธ์ค. (1) | 2024.01.23 |
์๋ฃ ๊ตฌ์กฐ(Data Structure), ์๊ณ ๋ฆฌ์ฆ(Algorithms) ๊ทธ๊ฒ ๋ญ์ผ... ? (0) | 2024.01.16 |
- ๋ฒ์ฉ๊ณ ์ ์๋ณ
- ๊ณต๊ฐ ๋ณต์ก๋
- 2024๋ ๋ชฉํ
- containerView
- 10808
- tipkit
- 2023๋ ํ๊ณ
- ์์ด ๋ด์ค
- ์๋ฐฉํฅ ์ฐ๊ฒฐ ๋ฆฌ์คํธ
- Container View Controller
- ์คํ
- C++
- 24๋ ํ๊ณ
- ์์ด ๊ณต๋ถ
- ํ๊ณ
- Swift
- ๋จ์ผ ์ฐ๊ฒฐ ๋ฆฌ์คํธ
- ๊ท๋๋ผ๋ฏธ ์์ด
- root view controller
- ์ ํ์์นด๋ฐ๋ฏธ
- ์ํํธ์คํฌ
- ๊ฐ๋ฐ์
- remainder
- ์๋ฃ ๊ตฌ์กฐ
- BOJ
- ๊ท๋๋ผ๋ฏธ ์์ด
- ํ
- ๊ดํธ์ ๊ฐ
- pageViewController
- Anyobject
- Total
- Today
- Yesterday