์ค์ํํธ๋ก ๊ตฌํํ๋ ์๋ฃ๊ตฌ์กฐ 2: ๋งํฌ๋ ๋ฆฌ์คํธ(Linked List)
๋งํฌ๋ ๋ฆฌ์คํธ (Linked List)
๋งํฌ๋ ๋ฆฌ์คํธ๋ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ง๊ณ ์๋ ๋ ธ๋๋ค์ ํฌ์ธํฐ๋ก ์ ํ์ ์ผ๋ก ์ฐ๊ฒฐํด ์ฌ์ฉํ๋ ์๋ฃ๊ตฌ์กฐ์ ๋๋ค. ์ญ์ ์ ์ฝ์ ์ O(1)์ ์๊ฐ๋ณต์ก๋๊ฐ ๊ฑธ๋ฆฌ๊ธฐ ๋๋ฌธ์(์ํ๋ ๋ ธ๋๊น์ง์ ํ์์๊ฐ ์ ์ธ) ๋น๋ฒํ๊ฒ ์ฝ์ ๊ณผ ์ญ์ ๊ฐ ํ์ํ ์ํฉ์ ์ ์ฉํ๊ฒ ์ฌ์ฉํ ์ ์์ต๋๋ค. ํ์ง๋ง ๋์์ ๋ฐฐ์ด์ฒ๋ผ ์ธ๋ฑ์ค๋ฅผ ํตํ Random Access๊ฐ ๋ถ๊ฐ๋ฅํ๊ณ , ์ฒ์๋ถํฐ ์ํ๋ ๋ฐ์ดํฐ๊ฐ ๋์ฌ ๋๊น์ง ํ์์ ์งํํด์ผํ๊ธฐ ๋๋ฌธ์ ํ์์๋ O(N)์ ์๊ฐ๋ณต์ก๋๊ฐ ์๊ตฌ๋๋ค๋ ๋จ์ ์ด ์์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ ํฌ์ธํฐ ๊ธฐ๋ฐ์ด๋ผ ๋๋ฒ๊น ์ด ์ด๋ ค์์ใ
๋ผ๋ ๋ง๋ค๊ธฐ
Node
๋จผ์ ๋ฐ์ดํฐ๋ฅผ ์ค์ ๋ก ์ ์ฅํ๊ณ , ๋ค์ ๋ ธ๋์ ์ฐธ์กฐ๊ฐ์ ์ ์ฅํ ๋ ธ๋ ์๋ฃ๊ตฌ์กฐ๋ฅผ ์ ์ํฉ์๋ค!
import Foundation
class Node<T: Equatable> {
let id: Int
let data: T
var next: Node?
init(id: Int, data: T, next: Node? = nil) {
self.id = id
self.data = data
self.next = next
}
}
id๋ ์ดํ์ ์ญ์ ์ ์ฝ์ ์ ์ฝ๊ฒ ํ์ธํ๊ธฐ ์ํด ๋ง๋ค์ด๋ ํ๋กํผํฐ ์ด๊ตฌ์, ์ ์ผ ์ค์ํ๊ฑด ์ค์ ๋ก ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ data ํ๋กํผํฐ์ ํ์ฌ ๋ ธ๋์ ๋ค์ ๋ ธ๋๋ฅผ ์ ์ฅํ next ํ๋กํผํฐ์ ๋๋ค.
Linked List
struct LinkedList<T: Equatable> {
var head: Node<T>?
var tail: Node<T>?
func showList() {
var now = head
print("===== Linked List ======")
while now != nil {
now?.next == nil
? print("id: \(now?.id) | data: \(now?.data)")
: print("id: \(now?.id) | data: \(now?.data) -> ")
now = now?.next
}
print("========================")
}
}
๋งํฌ๋ ๋ฆฌ์คํธ์ ํ๋กํผํฐ์๋ ๊ฐ์ฅ ์์ ์์นํ ๋ ธ๋๋ฅผ ๊ฐ๋ฆฌํค๋ head์ ๊ฐ์ฅ ๋ง์ง๋ง ๋ ธ๋๋ฅผ ๊ฐ๋ฆฌํค๋ tail๋ก ๊ตฌ์ฑ๋ฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ ํ์ฌ๊น์ง ๋งํฌ๋ ๋ฆฌ์คํธ์ ์ฐ๊ฒฐ๋์ด์๋ ๋ ธ๋๋ค์ ๋ชจ๋ ์์๋๋ก ์ถ๋ ฅํ showList๋ฅผ ๊ตฌํํด๋์์ต๋๋ค.
์ถ๊ฐ(add) - O(1)
mutating func add(node: Node<T>) {
// head node does not exist
if head == nil {
head = node
tail = node
return
}
// search for last node and attatch new
tail?.next = node
tail = node
}
์ถ๊ฐ ์ฐ์ฐ์ ๋ ๊ฐ์ง ๊ฒฝ์ฐ๊ฐ ์์ ์ ์์ต๋๋ค.
๋จผ์ , ์์ง ๋งํฌ๋ ๋ฆฌ์คํธ์ ์๋ฌด ๋ ธ๋๋ ์์ ๊ฒฝ์ฐ์ธ๋ฐ์, ์ด๋๋ head๊ฐ ๊ฐ๋ฆฌํค๋ ๋ ธ๋๊ฐ ์์ผ๋ ์ด๊ธฐ๊ฐ์ธ nil์ด ๋ค์ด์๊ฒ ์ฃ ? ๊ทธ๋์ head์ ๊ฐ์ ํ์ธํด๋ณด๊ณ nil์ด๋ผ๋ฉด head์ ์๋ก ๋ค์ด์จ ๋ ธ๋๋ฅผ ์ฐ๊ฒฐํด์ฃผ๊ณ , tail๋ nil์ผํ ๋ ์ฌ๊ธฐ์๋ ์๋ก์ด ๋ ธ๋๋ฅผ ์ฐ๊ฒฐํด์ค๋๋ค.
๋ค์์ ์ด๋ฏธ ๋งํฌ๋ ๋ฆฌ์คํธ์ ๋ฐ์ดํฐ๋ค์ด ๋ค์ด์๋ ๊ฒฝ์ฐ์ ๋๋ค. ์ด๋๋ ๊ฐ์ฅ ๋ง์ง๋ง ๋ ธ๋๋ฅผ ๊ฐ๋ฆฌํค๋ tail ํฌ์ธํฐ๋ก ์ฐพ์๊ฐ์ tail์ด ๊ฐ๋ฆฌํค๋ ๋ ธ๋์ ๋ค์๋ ธ๋์ ์ ๋ ธ๋๋ฅผ ์ฐ๊ฒฐํด์ค ๋ค, tail์ด ๊ฐ๋ฆฌํค๋ ๋ ธ๋๋ฅผ ์๋ก์ด ๋ ธ๋๋ก ๋ณ๊ฒฝํด์ค๋๋ค.
๋ฌด์กฐ๊ฑด tail์ ์ฐธ์กฐํด์ ์๋ ธ๋๋ฅผ ์ฐ๊ฒฐ๋ง ํด์ฃผ๋ฉด ๋๋ ํญ์ O(1)์ ์๊ฐ๋ณต์ก๋๊ฐ ๋๊ฒ ์ฃ ?
ํ์(search) - O(N)
๋ค์์ ํ์ ์ฐ์ฐ์ ๋๋ค. ๋งํฌ๋ ๋ฆฌ์คํธ๋ Random Access๊ฐ ๋ถ๊ฐ๋ฅํด์ ํน์ ํ ๋ ธ๋์ ์ ๊ทผํ๋ ค๋ฉด ํญ์ ์ ์ผ ์ฒ์ ๋ ธ๋์ธ head ๋ถํฐ ์ํ๋ ๋ ธ๋๋ฅผ ์ฐพ์ ๋๊น์ง next ํ๋กํผํฐ๋ฅผ ํตํด ๋ค์๋ ธ๋๋ฅผ ์ฌ๊ท์ ์ผ๋ก ํ์ํด์ผํฉ๋๋ค.
์ด๋ ๊ฒ ๋ ธ๋๊ฐ ์ค๊ฐ์ ์๋ ๋ ธ๋๊น์ง ํ์์ ํ๊ณ ์ถ๋ค๊ณ ํด๋ณด๊ฒ ์ต๋๋ค. ์ฐพ๊ณ ์ถ์ ๋ ธ๋์ id๋ 4์ด๋ค์.
ํ์์ ์์ํ๊ธฐ ์ํด head ์ tail์ด ์๋ ์ปค์์ ์ญํ ์ ํ ํฌ์ธํฐ now๋ฅผ ๋ง๋ค์ด์ฃผ๊ฒ ์ต๋๋ค.
์ด์ now๋ฅผ ์์ง์ด๋ฉด์ now ๊ฐ ๊ฐ๋ฆฌํค๋ id๊ฐ 4๊ฐ ๋ ๋๊น์ง ์ปค์๋ฅผ ์์ง์ฌ์ค์๋ค. next ํ๋กํผํฐ๋ ํญ์ ์์ ์ ๋ค์ ๋ ธ๋๋ฅผ ๊ฐ๋ฆฌํค๊ณ ์๊ธฐ ๋๋ฌธ์ ์ด๋ฅผ ์ด์ฉํ๋ฉด ์ปค์๋ฅผ ์ด๋์ํค๋ ๊ฑด ์ฝ์ต๋๋ค.
now = now.next
์ด๋ ๊ฒ์! ๊ฐ๋จํ์ฃ ? id๋ฅผ ๋ฐ๊ฒฌํ๋ค๋ฉด ํด๋น ๋ ธ๋์ ์ฐธ์กฐ ๊ฐ์ ๊ทธ๋๋ก ๋ฐํํ๊ณ , id๋ฅผ ์ฐพ์ง ๋ชปํ๋ค๋ฉด ๋ง์ง๋ง ๋ ธ๋๊น์ง ์ด๋ํด nil์ ๋ฐํํ๊ฒ ํ๋ฉด ๋ฉ๋๋ค.
func searchNode(with data: T) -> Node<T>? {
var now = head
while now?.data != data && now != nil {
now = now?.next
}
return now
}
์ฝ์ (insert) - O(1) or O(N)
์ฝ์ ์ฐ์ฐ์ ๊ฐ์ฅ ๋ค๊ฐ ์๋ ์ด๋ค ํน์ ํ ๋ ธ๋์ ์์ด๋ ๋ค์ ์๋ก์ด ๋ ธ๋๋ฅผ ๋ผ์๋ฃ๋ ๊ฒ์ ์๋ฏธํ๋๋ฐ์, ์ฝ์ ์ ํ๋ ค๋ฉด ์ํ๋ ์ง์ ๊น์ง์ ํ์์ด ์ ํ๋์ด์ผ ํฉ๋๋ค.
ํ์์์์ ์์๋ฅผ ๊ทธ๋๋ก ์ฌ์ฉํด์ id๊ฐ 4์ธ ๋ ธ๋๋ฅผ ์ฐพ์๋ค๊ณ ํด๋ณด๊ฒ ์ต๋๋ค. ์ฌ๊ธฐ์ ๋ชฉํ๋ id๊ฐ 4์ธ ๋ ธ๋์ id๊ฐ 5์ธ ๋ ธ๋ ์ฌ์ด์ ์๋ก์ด ๋ ธ๋๋ฅผ ์ฝ์ ํ๋ ๊ฒ์ ๋๋ค.
์๋ก์ด ๋ ธ๋์ ์ฝ์ ์ ๋ ธ๋๋ค ์ฌ์ด์ ํฌ์ธํฐ๋ง ๋ฐ๊พธ๋ฉด ์ฝ๊ฒ ๊ฐ๋ฅํ ๊ฒ ๊ฐ์ต๋๋ค.
๋ฐฉ๊ธ ์ฐพ์ ๋ ธ๋๊ฐ ๊ฐ๋ฆฌํค๋ ๋ค์ ๋ ธ๋๋ฅผ ์๋ก์ด ๋ ธ๋ ๋ํ ๊ฐ๋ฆฌํค๊ฒ ๋ง๋ค๊ณ ,
์ฐพ์ ๋ ธ๋๊ฐ ์ด์ ์๋ก ์ฝ์ ํ ๋ ธ๋๋ฅผ ๊ฐ๋ฆฌํค๊ฒ ํ๋ฉด ๊ฐ๋จํ๊ฒ ์ฝ์ ์ฐ์ฐ์ด ์์ฑ๋ฉ๋๋ค. ๋ชฉํ ๋ ธ๋๋ฅผ ์ฐพ๊ธฐ ์ํด์ ํ์์ฐ์ฐ์ ์ํํ๊ธฐ ๋๋ฌธ์ O(N)์ ์๊ฐ๋ณต์ก๋๊ฐ ๋จผ์ ์๊ตฌ๋๊ณ , ๊ทธ ์ดํ์ ์ฝ์ ์ ํฌ์ธํฐ์ ๋ณ๊ฒฝ๋ง ์๊ธฐ ๋๋ฌธ์ O(1)์ ๋๋๊ฒ ๋ฉ๋๋ค.
O(1)๋ก ์ฝ์ ์ด ๋๋ ๊ฒฝ์ฐ๋ ์๋๋ฐ์, head๋ tail ์์ด๋ ๋ค์ ์๋ก์ด ๋ ธ๋๋ฅผ ์ฝ์ ํ๋ฉด ํ์์ด ํ์์๊ธฐ ๋๋ฌธ์ O(1)์ ์ฝ์ ์ด ๊ฐ๋ฅํฉ๋๋ค.
mutating func insert(node: Node<T>, after id: Int) {
var now = head
while now?.id != id && now?.next != nil {
now = now?.next
}
node.next = now?.next
now?.next = node
}
mutating func insert(node: Node<T>, before id: Int) {
var now = head
if now?.id == id {
head = node
node.next = now
return
}
while now?.next?.id != id && now?.next != nil {
now = now?.next
}
node.next = now?.next
now?.next = node
}
์ญ์ (delete) - O(1) or O(N)
์ญ์ ์ฐ์ฐ์ ์ฝ์ ๊ณผ ์ ์ฌํฉ๋๋ค! ๋จผ์ ์ญ์ ํ ๋ ธ๋๋ฅผ ์ฐพ๊ณ , ๊ทธ ์์ ์๋ ๋ ธ๋์ next ํฌ์ธํฐ๋ฅผ ์ญ์ ํ ๋ ธ๋์ ๋ค์ ๋ ธ๋๋ก ์ ํด์ฃผ๋ฉด ๋๊ฒ ์ฃ ?
์ด๋ฒ์๋ ์ญ์ ํ ๋ ธ๋๊น์ง ์ฐพ์๊ฐ๋ฉด ์ด์ ๋ ธ๋์ ์ ๊ทผํ ๋ฐฉ๋ฒ์ด ์๊ธฐ ๋๋ฌธ์ ๋ค์ ๋ ธ๋๊ฐ ์ญ์ ํ ๋ ธ๋๊ฐ ๋ ๋๊น์ง now ํฌ์ธํฐ๋ฅผ ์์ง์ฌ์ค๋๋ค.
๊ทธ๋ฆฌ๊ณ ์ญ์ ํ ๋ ธ๋๋ฅผ ๊ฑด๋๋ฐ๊ณ ๊ทธ ๋ค์ ๋ ธ๋์ ํ์ฑ ํฌ์ธํฐ๋ฅผ ์ฐ๊ฒฐํด์ค๋๋ค.
์ง ! 4๋ฒ ๋ ธ๋๋ ๋ ์ด์ ์ฐธ์กฐํ๊ณ ์๋ ๋ ธ๋๊ฐ ์์ผ๋ ๋ฉ๋ชจ๋ฆฌ์์ ํด์ ๋๊ฒ ์ฃ ? ์ด๋ฒ์๋ ๊ฐ๋จํ๊ฒ ์ญ์ ๊ฐ ์๋ฃ๋ฉ๋๋ค!
์ญ์ ์ญ์๋ ์ฝ์ ์ฒ๋ผ ํ์์ O(N), ์ญ์ ์ O(1)์ ์๊ฐ๋ณต์ก๋๊ฐ ์๊ตฌ๋๊ธฐ ๋๋ฌธ์ ์ญ์ ํ ๋ ธ๋๊ฐ head ๋ tail์ด ์๋ ๋๋ O(N), head๋ tail์ผ ๋๋ O(1)์ด ์๊ฐ๋ณต์ก๋๊ฐ ๋ฉ๋๋ค.
mutating func delete(node: Node<T>) -> Bool {
var now = self.head
// if target node is at head
if now === node {
if self.head === self.tail { self.tail = nil }
self.head = now?.next
return true
}
while now?.next !== node && now?.next != nil {
now = now?.next
}
// no matching node to delete
if now == nil { return false }
if now?.next === tail {
tail = now
}
// delete node
now?.next = now?.next?.next
return true
}
์ ์ฒด์ฝ๋
์๋ฃ๊ตฌ์กฐ ์๋ฆฌ์ฆ์ ์ฝ๋๋ค์ ์ด ๋ ํฌ์์ ๋ชจ๋ ํ์ธํ ์ ์์ด์!
'๐ฎ ์จ-์์ค > ๐ฆด ์๋ฃ๊ตฌ์กฐ' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
๋๊ธ
์ด ๊ธ ๊ณต์ ํ๊ธฐ
-
๊ตฌ๋
ํ๊ธฐ
๊ตฌ๋ ํ๊ธฐ
-
์นด์นด์คํก
์นด์นด์คํก
-
๋ผ์ธ
๋ผ์ธ
-
ํธ์ํฐ
ํธ์ํฐ
-
Facebook
Facebook
-
์นด์นด์ค์คํ ๋ฆฌ
์นด์นด์ค์คํ ๋ฆฌ
-
๋ฐด๋
๋ฐด๋
-
๋ค์ด๋ฒ ๋ธ๋ก๊ทธ
๋ค์ด๋ฒ ๋ธ๋ก๊ทธ
-
Pocket
Pocket
-
Evernote
Evernote