์ฐ๊ฒฐ ๋ฆฌ์คํธ(Linked List)
- ์ฐ์์ ์ธ ๋ฉ๋ชจ๋ฆฌ ์์น์ ์ ์ฅ๋์ง ์๋ ์ ํ ์๋ฃ๊ตฌ์กฐ
- ๋ฐ์ดํฐ ํ๋ + ๋ค์์ ๋ ธ๋์ ๋ํ ์ฐธ์กฐ ๋ฅผ ํฌํจํ๋ ๋ ธ๋๋ก ๊ตฌ์ฑ
์ฐ๊ฒฐ ๋ฆฌ์คํธ๋ฅผ ์ฌ์ฉํ๋ ์ด์ ?
๋ฐฐ์ด์ ๋ฐฐ์ด์ ํฌ๊ธฐ๊ฐ ๊ณ ์ ๋์ด ์์ด ๋ฏธ๋ฆฌ ์์์ ์์ ๋ํด ํ ๋น๋ฐ์์ผ ํ๋ค. ๊ทธ๋ ๊ธฐ ๋๋ฌธ์ ์๋ก์ด ์์ ์ฝ์ ์ ๋น์ฉ์ด ๋ง์ด ๋ ๋ค. (๊ณต๊ฐ ๋ง๋ค๊ธฐ + ๊ธฐ์กด ์์์ ์ด๋)
์ฅ์
- ๋์ ์ธ ํฌ๊ธฐ๋ฅผ ๊ฐ์ง๋ค.
- ์ฝ์ /์ญ์ ๊ฐ ์ฉ์ดํ๊ณ ์๋๊ฐ ๋น ๋ฅด๋ค.
๋จ์
- Random Access๊ฐ ๋ถ๊ฐํ๊ธฐ ๋๋ฌธ์ ์ฒซ ๋ฒ์งธ ๋ ธ๋๋ถํฐ ์์ฐจ์ ์ผ๋ก ์ก์ธ์คํด์ผํ๋ค.
- ๊ฒ์ ์๋๊ฐ ๋๋ฆฌ๋ค.
- ์ ์ฅ ๊ณต๊ฐ์ ํจ์จ์ด ๋์ง ์๋ค.
์ถ๊ฐ(add)
- ๋
ธ๋๊ฐ ์๋ฌด๊ฒ๋ ์์ ๋
- head = nil, tail = nil
- head ๊ฐ์ ํ์ธ ํ ์๋ก์ด ๋ ธ๋๋ฅผ ์ฐ๊ฒฐํ๊ณ tail๋ ๋์ผํ๊ฒ ์๋ก์ด ๋ ธ๋๋ฅผ ์ฐ๊ฒฐํ๋ค.
- ์ด๋ฏธ ๋ฐ์ดํฐ๊ฐ ์กด์ฌํ๋ ๊ฒฝ์ฐ
- ๊ฐ์ฅ ๋ง์ง๋ง ๋ ธ๋๋ฅผ ๊ฐ๋ฆฌํค๋ tail์ ์ฐพ๊ณ , ๊ทธ ๋ค์ ๋ ธ๋์ ์๋ก์ด ๋ ธ๋๋ฅผ ์ฐ๊ฒฐํ๋ค.
- ๊ฐ์ฅ ๋ง์ง๋ง ๋ ธ๋๊ฐ ๋ ์๋ก์ด ๋ ธ๋๋ฅผ tail์ด ๊ฐ๋ฆฌํค๋ ๋ ธ๋๋ก ๋ณ๊ฒฝํ๋ค.
ํ์(Search)
- ์ ์ผ ์ฒ์ ๋ ธ๋์ธ head๋ถํฐ ํ์ผ ๋ ธ๋๋ฅผ ์ฐพ์ ๋๊น์ง next๋ฅผ ํตํด ๋ค์ ๋ ธ๋๋ฅผ ํ์ํ๋ค.
- ํฌ์ธํฐ ์ญํ ์ ํ๋ now๋ฅผ ํตํด ํ๊ฒ์ ์ฐพ์ ํ์ํ๋ค.
์ฝ์ (Insert)
- ํน์ ๋ ธ๋์ ์์ด๋ ๋ค์ ์๋ก์ด ๋ ธ๋๋ฅผ ์ฝ์ ํ๋ ค๋ฉด ํ๊ฒ ์ง์ ๊น์ง ํ์์ ๋จผ์ ์งํํ๋ค.
- ํ๊ฒ ๋ ธ๋ ๋ค์ ์๋ก์ด ๋ ธ๋๋ฅผ ์ถ๊ฐํ๋ค. ํฌ์ธํฐ๋ฅผ ๋ฐ๊พธ์ด์ค๋ค.
- ํ๊ฒ ๋ ธ๋๋ฅผ ์ฐพ๊ธฐ ์ํด์ ํ์ ์ฐ์ฐ์ ์ํํ๊ธฐ ๋๋ฌธ์ O(n)์ ์๊ฐ๋ณต์ก๋๊ฐ ์๊ตฌ๋๊ณ , ์ดํ ํฌ์ธํฐ ๋ณ๊ฒฝ์ ์ํํ์ฌ O(1)์ ์๊ฐ๋ณต์ก๋๊ฐ ์๊ตฌ๋๋ค.
์ญ์ (Delete)
- ์ฝ์ ์ฐ์ฐ๊ณผ ์ ์ฌํ๊ฒ ์ญ์ ํ ๋ ธ๋๋ฅผ ํ์ํ๋ค.
- ๋ ธ๋์ next ํฌ์ธํฐ๋ฅผ ์ญ์ ํ ๋ ธ๋์ ๋ค์ ๋ ธ๋๋ก ์ฐ๊ฒฐ์ ๋ฐ๊พธ์ด์ค๋ค.
๊ตฌํ
Node.swift
class Node<T: Equatable> {
let data: T
var next: Node?
init(data: T, next: Node? = nil) {
self.data = data
self.next = next
}
}
LinkedList.swift
struct LinkedList<T: Equatable> {
var head: Node<T>?
var tail: Node<T>?
// ์ถ๊ฐ
mutating func add(node: Node<T>) {
// (1) ๋
ธ๋๊ฐ ์๋ฌด๊ฒ๋ ์์ ๋
if head == nil {
head = node
tail = node
return
}
// (2) ์ด๋ฏธ ๋ฐ์ดํฐ๊ฐ ์กด์ฌํ๋ ๊ฒฝ์ฐ
// tail์ ๋ค์ ๋
ธ๋์ ์๋ก์ด ๋
ธ๋๋ฅผ ์ฐ๊ฒฐํ๊ณ , ๊ทธ ์๋ก์ด ๋
ธ๋๋ฅผ tail์ด ๊ฐ๋ฆฌํค๋ ๋
ธ๋๋ก ๋ณ๊นใ
๊ธฐ
tail?.next = node
tail = node
}
// ํ์
func search(data: T) -> Node<T>? {
// ํฌ์ธํฐ ์ญํ ์ ํ๋ now
guard var now = head else { return nil }
// now์ ๋ฐ์ดํฐ์ ํ๊ฒ ๋ฐ์ดํฐ๋ฅผ ๋น๊ตํ๊ณ , ์ฐพ์ ๋๊น์ง next๋ฅผ ํตํด ํ์ํ๊ธฐ
while now.data != data {
guard let next = now.next else { return nil }
now = next
}
return now
}
// ์ฝ์
func insert(index: Int, data: T) {
// ํฌ์ธํฐ ์ญํ ์ ํ๋ now
guard var now = head else { return }
// ํ์ ์์ ์ธ๋ฑ์ค
var currentIndex = 0
// (1) now๋ฅผ ๋ค์ ๋
ธ๋๋ก ์ด๋ํ๋ฉด์ ์ฝ์
ํ๋ ค๋ ์์น ์ฐพ๊ธฐ
while currentIndex < index {
guard let nowNext = now.next else { return }
now = nowNext
currentIndex += 1
}
// (2) ํ๊ฒ ๋
ธ๋ ๋ค์ ์๋ก์ด ๋
ธ๋ ์ฝ์
ํ๊ธฐ
now.next = Node(data: data, next: now.next)
}
// ์ญ์
mutating func remove(node: Node<T>) {
// ํฌ์ธํฐ ์ญํ ์ ํ๋ now
guard var now = head else { return }
// (1) head๋ฅผ ์ญ์ ํ๋ ๊ฒฝ์ฐ
guard now !== node else {
head = now.next
return
}
// (2) ํน์ ๋
ธ๋๋ฅผ ์ญ์ ํ๋ ๊ฒฝ์ฐ - ํน์ ๋
ธ๋ ํ์ํ๊ธฐ
while now.next !== node {
guard let nowNext = now.next else { return }
now = nowNext
}
// (3) ๋ง์ง๋ง ๋
ธ๋ ์ฒดํฌ
if now.next === tail {
tail = now
}
now.next = now.next?.next
}
// print
func printLinkedList() {
guard var now = head else { return }
while now != nil {
guard let nowNext = now.next else {
print("data: \(now.data), next: \(now.next?.data)")
return
}
print("data: \(now.data), next: \(nowNext.data)")
guard let nowNext = now.next else { return }
now = nowNext
}
}
}
์คํ ๊ฒฐ๊ณผ