์ค์ํํธ๋ก ๊ตฌํํ๋ ์๋ฃ๊ตฌ์กฐ 4: ๋๋ธ ๋งํฌ๋ ๋ฆฌ์คํธ(Doubly Linked List)
๋๋ธ ๋งํฌ๋ ๋ฆฌ์คํธ(Doubly Linked List)
๋๋ธ ๋งํฌ๋ ๋ฆฌ์คํธ๋ ๋งํฌ๋ ๋ฆฌ์คํธ์ ๊ฐ๋ ์ ๊ฐ์ง๋ง ๊ฐ ๋ ธ๋๊ฐ ์์ ์ ์ด์ ๋ ธ๋๊น์ง ์๊ณ ์๋ค๋ ์ ์์ ๋ค๋ฆ ๋๋ค. ๊ธฐ์กด ๋งํฌ๋ ๋ฆฌ์คํธ๋ ๊ฐ ๋ ธ๋๊ฐ ๋ฐ๋ก ๋ค์ ๋ ธ๋์ ์ฐธ์กฐ ๊ฐ๋ง ์๊ณ ์์ง๋ง, ์ด๋ฒ์๋ ์์ ์ ์์ชฝ์ ๋ ธ๋๋ฅผ ๋ชจ๋ ์ฐธ์กฐํ๊ธฐ ๋๋ฌธ์ ์ญ์ ๋ ์ฝ์ ์ฐ์ฐ์ ๊ตฌํ์ด ์กฐ๊ธ ๋ ์ฌ์์ง๋๋ค.
๋ผ๋ ๋ง๋ค๊ธฐ
Node
import Foundation
class Node<T: Equatable> {
let id: Int
let data: T
var next: Node? = nil
var prev: Node? = nil
init(id: Int, data: T) {
self.id = id
self.data = data
}
}
๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๊ณ ๋ฆฌ์คํธ๋ฅผ ๊ตฌ์ฑํ ๋ ธ๋๋ ๊ฐ์ ์์ ์ id, ์ ์ฅํ ๋ฐ์ดํฐ, ์ด์ ๋ ธ๋์ ๋ํ ์ฐธ์กฐ๊ฐ๊ณผ ๋ค์ ๋ ธ๋์ ๋ํ ์ฐธ์กฐ๊ฐ์ ๊ฐ์ง๋๋ค.
Doubly Linked List
struct DoublyLinkedList<T: Equatable> {
var head: Node<T>?
var tail: Node<T>?
var front: Node<T>? {
return head
}
var back: Node<T>? {
return tail
}
func showAll() {
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 ํ๋กํผํฐ๋ฅผ ๊ฐ์ง๋๋ค. head ๋ ํ์ฌ ๋งํฌ๋ ๋ฆฌ์คํธ์์ ๊ฐ์ฅ ์์ ์๋ ๋ ธ๋๋ฅผ ๊ฐ๋ฆฌํค๊ณ , tail์ ๊ฐ์ฅ ๋ค์ ์๋ ๋ ธ๋๋ฅผ ๊ฐ๋ฆฌํต๋๋ค.
front, back ์ head์ tail ํ๋กํผํฐ๋ฅผ ํตํด์ ๊ฐ์ฅ ์ ๋ ธ๋์ ๋ง์ง๋ง ๋ ธ๋์ ์ฐธ์กฐ ๊ฐ์ ๋ฐํํ๊ณ , ๋งํฌ๋ ๋ฆฌ์คํธ์ ๋ ธ๋ ๋ชฉ๋ก์ ์์๋๋ก ํ์ธํ ์ ์๋ showAll ๋ฉ์๋๋ฅผ ๊ตฌํํ์ต๋๋ค.
์ถ๊ฐ (add) - O(1)
์๋ก์ด ๋ ธ๋๋ฅผ ๋ฆฌ์คํธ ๊ฐ์ฅ ๋์ ์ถ๊ฐํ๋ ์ฐ์ฐ์ tail ํฌ์ธํฐ๋ฅผ ์ด์ฉํด์ O(1)์ ์ํํ ์ ์์ต๋๋ค. ๋ ๊ฐ์ง ๊ฒฝ์ฐ๊ฐ ์์ ์ ์๋๋ฐ์,
1) ๋งํฌ๋ ๋ฆฌ์คํธ์ ์๋ฌด ๋ ธ๋๋ ์๋ ๊ฒฝ์ฐ
์ด ๊ฒฝ์ฐ์๋ ์๋ก์ด ๋ ธ๋๋ฅผ head์ tail์ด ๊ฐ๋ฆฌํค๊ฒ ํ๋ ๊ฒ์ผ๋ก ์ฝ๊ฒ ๋ ธ๋๋ฅผ ์ถ๊ฐํ ์ ์์ต๋๋ค.
2) ๋งํฌ๋ ๋ฆฌ์คํธ์ ๋ ธ๋๊ฐ ์กด์ฌํ๋ ๊ฒฝ์ฐ
์ด๋ฏธ ๋ฆฌ์คํธ์ ๋ ธ๋๊ฐ ์กด์ฌํ๋ ๊ฒฝ์ฐ์๋ tail์ด ๊ฐ๋ฆฌํค๋ ๋ค์ ๋ ธ๋๋ฅผ ์๋ก์ด ๋ ธ๋๋ก ์ง์ ํ๊ณ , ์๋ก์ด ๋ ธ๋์ ์ด์ ๋ ธ๋๋ฅผ tail์ด ๊ฐ๋ฆฌํค๋ ๋ ธ๋๋ก ์ง์ ํฉ๋๋ค.
๊ทธ๋ฆฌ๊ณ ์ด์ ๋ง์ง๋ง ๋ ธ๋๊ฐ ๋ณ๊ฒฝ๋์๊ธฐ ๋๋ฌธ์ tail๋ ํ ์นธ ์ค๋ฅธ์ชฝ์ผ๋ก ์ด๋์์ผ์ค๋๋ค.
์ด๋ค ๊ฒฝ์ฐ๋ ์ง tail์ ์ฌ์ฉํด ๋ง์ง๋ง ๋ ธ๋๋ฅผ ๋ฐ๋ก ์ฐธ์กฐํ ์ ์๊ธฐ ๋๋ฌธ์ ํญ์ O(1)์ด ๋ณด์ฅ๋ฉ๋๋ค. ์ ๋ก์ง์ ๊ตฌํํ๋ฉด ์ด๋ ๊ฒ ๋๊ฒ ์ฃ !
mutating func add(node: Node<T>) {
if self.head == nil {
self.head = node
self.tail = node
return
}
self.tail?.next = node
node.prev = self.tail
self.tail = node
}
ํ์ (search) - O(N)
ํน์ ํ ๋ ธ๋๋ฅผ ํ์ํ๊ธฐ ์ํด์๋ ๋ฆฌ์คํธ์ ์ฒซ ๋ ธ๋์ธ head๋ถํฐ ๋ง์ง๋ง ๋ ธ๋์ธ tail ๊น์ง ๋ชจ๋ ๋ ธ๋๋ฅผ ๊ฒ์ฌํด๋ณด์์ผ ์ํ๋ ๋ ธ๋๋ฅผ ํ์ํ ์ ์์ต๋๋ค. ์ด๋ฅผ ์ํด์ ํ์ฌ ๋ ธ๋๋ฅผ ๊ฐ๋ฆฌํค๋ ์ปค์์ธ now ํฌ์ธํฐ๋ฅผ ์ฌ์ฉํ๋ฉด ๋ค์ ๋ ธ๋๋ก ๊ณ์ ์ด๋ํ ์ ์์ต๋๋ค.
now ๋ฅผ ์ด๋์ํค๋ ค๋ฉด ์ฌ๊ท์ ์ผ๋ก, ํน์ ๋ฐ๋ณต๋ฌธ์ ํตํด์ ํ์ฌ ๋ ธ๋์ ๋ค์ ๋ ธ๋๋ฅผ now๋ก ๋ณ๊ฒฝํด์ฃผ๋ฉด ๋ฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ ์๋ก์ด now ๊ฐ ๊ฐ๋ฆฌํค๋ ๋ ธ๋๊ฐ ์ํ๋ ๋ ธ๋๋ผ๋ฉด ํด๋น ๋ ธ๋๋ฅผ ๊ทธ๋๋ก ๋ฐํํด์ฃผ๋ฉด ๋๊ฒ ์ฃ . ํ์์ ์ต์ ์ ๊ฒฝ์ฐ์๋ ์ ์ฒด ๋ ธ๋๋ฅผ ๋ค ๋์๋ด์ผ ํ๊ธฐ ๋๋ฌธ์ O(N)์ ์๊ฐ๋ณต์ก๋๊ฐ ์๊ตฌ๋๊ณ , ์ด์ค์ผ๋ก ์ฐ๊ฒฐ๋ ๋ฆฌ์คํธ๊ฐ ๊ทธ๋ค์ง ๋์์ด ๋์ง๋ ์์ต๋๋ค.
mutating func searchNode(with data: T) -> Node<T>? {
var now = self.head
while now?.data != data && now !== tail {
now = now?.next
}
return now
}
์ฝ์ (insert) - O(1) or O(N)
์ด์ค์ผ๋ก ์ฐ๊ฒฐ๋ ๋๋ถ์ ์ฝ์ ์ด ์กฐ๊ธ ๋ ์ฌ์์ก์ต๋๋ค. ์ฝ์ ์ฐ์ฐ์ ๊ฒฝ์ฐ์ ๋ฐ๋ผ์ O(1)์ ๋๋ ์๋ ์๊ณ , O(N)์ด ๊ฑธ๋ฆด ์๋ ์์ต๋๋ค.
1) ์ฝ์ ํ ์์น๊ฐ head๋ tail์ผ ๋ - O(1)
์๋ก์ด ๋ ธ๋๋ฅผ ์ฝ์ ํ ์์น๊ฐ head ๋ tail์ ์๋ค๋ผ๋ฉด ๋ณ๋์ ํ์๊ณผ์ ์์ด ๊ณง๋ฐ๋ก ์ฝ์ ์ด ๊ฐ๋ฅํ๊ธฐ ๋๋ฌธ์ ์๊ฐ๋ณต์ก๋๊ฐ O(1)์ด ๋ฉ๋๋ค.
4๋ฒ๊ณผ 5๋ฒ ๋ ธ๋ ์ฌ์ด์ ์ ๋ ธ๋๋ฅผ ๋ผ์ ๋ฃ๊ณ ์ถ๋ค๊ณ ํด๋ณด๊ฒ ์ต๋๋ค.
์ฐ๋ฆฌ๋ ๋ง์ง๋ง ๋ ธ๋๊ฐ tail์ด๋ผ๋ ์ ๋ณด๋ฅผ ๊ฐ์ง๊ณ ์๊ธฐ ๋๋ฌธ์ tail์ ์ด์ ๋ ธ๋๋ฅผ ์ฐธ์กฐํด ๊ทธ ๋ค์ ๋ ธ๋๋ฅผ ์๋ก์ด ๋ ธ๋๋ก ์ง์ ํ๊ณ ,
์๋ก์ด ๋ ธ๋์ ์ด์ ๋ ธ๋๋ฅผ tail์ ์ด์ ๋ ธ๋๋ก ์ง์ ํฉ๋๋ค.
์ด์ ์ด์ ๋ ธ๋์ ์ ๋ ธ๋์ ์ฐ๊ฒฐ์ ๋๋ฌ์ผ๋ ๋ง์ง๋ง ๋ ธ๋์ธ tail์ ์ด์ ๋ ธ๋๋ฅผ ์ ๋ ธ๋๋ก, ์ ๋ ธ๋์ ๋ค์ ๋ ธ๋๋ฅผ tail๋ก ์ง์ ํด์ฃผ๋ฉด ์๋ก์ด ๋ ธ๋์ ์ฝ์ ์ด ์์ฑ๋ฉ๋๋ค.
2) ์ฝ์ ํ ์์น๊ฐ head๋ tail์ด ์๋ ๋ - O(N)
์ฝ์ ํ ์์น๊ฐ head๋ tail์ด ์๋๋ผ๋ฉด ํด๋น ์์น๋ฅผ ํ์์ ํตํด ์ฐพ์์ฃผ์ด์ผ ํฉ๋๋ค. ๋๋ฌธ์ ์์น๋ฅผ ํ์ํ๋ ์๊ฐ O(N)๊ณผ 1๋ฒ ์ฒ๋ผ ์ค์ ์ฝ์ ์ ์งํํ๋ ๊ณผ์ O(1) ์ด ์๊ตฌ๋์ด์ ์๊ฐ ๋ณต์ก๋๋ O(N)์ด ๋ฉ๋๋ค. ํ์ + ์ฝ์ ์ด ์ค์ ๋ก ์๊ตฌ๋๋ ๊ฒ์ด์ฃ .
mutating func insert(node: Node<T>, after id: Int) {
guard head != nil else { return }
var now = self.head
if id == self.tail!.id {
self.add(node: node)
}
while now?.id != id && now != nil {
now = now?.next
}
if now === self.tail {
self.tail = node
}
node.next = now?.next
now?.next?.prev = node
now?.next = node
node.prev = now
}
mutating func insert(node: Node<T>, before id: Int) {
guard head != nil else { return }
var now = self.head
if id == self.tail?.id {
now = self.tail
} else {
while now?.id != id && now != nil {
now = now?.next
}
}
if now === self.head {
self.head = node
}
now?.prev?.next = node
node.prev = now?.prev
now?.prev = node
node.next = now
}
์ญ์ (delete) - O(1) or O(N)
์ญ์ ์ฐ์ฐ์ ๊ธฐ๋ณธ์ ์ผ๋ก ์ฝ์ ๊ณผ ๋์ผํ๊ฒ ํน์ ํ ๋ ธ๋๊น์ง์ ํ์์ด ํ์ํ๊ณ ์ดํ์ ์ญ์ ๊ฐ ์งํ๋ฉ๋๋ค. ๋ฐ๋ผ์ ์ญ์ ํ ๋ ธ๋๊ฐ head๋ tail์ผ ๊ฒฝ์ฐ๋ ํ์์ด ํ์์์ผ๋ O(1)์ด ๋๊ณ , ๊ทธ ์ธ์ ๋ ธ๋๋ค์ O(N)์ด ๋ฉ๋๋ค.
์ญ์ ํ๋ ๊ณผ์ ์ ์๋์ ๊ฐ์ต๋๋ค.
3๋ฒ ๋ ธ๋๋ฅผ ์ญ์ ํ๋ค๊ณ ํด๋ณผ๊ฒ์!
์ญ์ ํ ๋ ธ๋์ ๋ค์ ๋ ธ๋๊ฐ ์ญ์ ํ ๋ ธ๋์ ์ด์ ๋ ธ๋๋ฅผ ๊ฐ๋ฆฌํค๊ฒ ํฉ๋๋ค.
๊ทธ๋ฆฌ๊ณ ์ญ์ ํ ๋ ธ๋์ ์ด์ ๋ ธ๋๊ฐ ์ญ์ ํ ๋ ธ๋์ ๋ค์ ๋ ธ๋๋ฅผ ๊ฐ๋ฆฌํค๊ฒ ํฉ๋๋ค. ๊ทธ๋ฆผ์์ ๋ณผ ์ ์๋ฏ์ด ์ด์ 3๋ฒ ๋ ธ๋๋ now ํฌ์ธํฐ์ ์ํด์๋ง ์ฐธ์กฐ๊ฐ ๋๋๋ฐ์, now ํฌ์ธํฐ๋ ์ญ์ ํจ์๊ฐ ์ข ๋ฃ๋๋ฉด ํจ๊ป ์ฌ๋ผ์ง๋ ๋ณ์์ด๊ธฐ ๋๋ฌธ์ ARC์ ์ํด ํจ์๊ฐ ์ข ๋ฃ๋๋ฉด์ 3๋ฒ ๋ ธ๋๋ ์ฌ๋ผ์ง๊ฒ ๋ฉ๋๋ค.
์ ๊ณผ์ ์ ๊ตฌํํ๋ฉด ์ด๋ ๊ฒ ๋๊ฒ ์ฃ ?
mutating func deleteNode(with id: Int) -> Node<T>? {
var now = self.head
if id == self.tail?.id {
now = self.tail
} else {
while now?.id != id && now != nil {
now = now?.next
}
}
let deleted = now
deleted?.next?.prev = deleted?.prev
deleted?.prev?.next = deleted?.next
if deleted === head {
self.head = deleted?.next
}
if deleted === tail {
self.tail = deleted?.prev
}
return deleted
}
๋ฆฌ์คํธ ๋ค์ง๊ธฐ - O(N)
๋ง์ง๋ง์ผ๋ก ์ผ๋ฐ ๋งํฌ๋ ๋ฆฌ์คํธ์์๋ ํ ์ ์๊ณ ๋๋ธ ๋งํฌ๋ ๋ฆฌ์คํธ์์๋ง ํ ์ ์๋ ๋ฐ์ ์ฐ์ฐ์ ์๊ฐํ๊ณ ๋ง์น๋ ค๊ณ ํฉ๋๋ค! ๊ฐ ๋ ธ๋๋ค์ ์์ ์ ์ด์ ๊ณผ ๋ค์ ๋ ธ๋ ์ ๋ณด๋ฅผ ๊ฐ์ง๊ณ ์๊ธฐ ๋๋ฌธ์ ์ด์ ์ ๋ค์์ผ๋ก, ๋ค์์ผ๋ก ์ด์ ์ผ๋ก ๋ณ๊ฒฝํด์ฃผ๋ฉด ๋ฉ๋๋ค.
์ด๋ ๊ฒ ์๋ ๋ฆฌ์คํธ๋ฅผ next์ prev๋ฅผ ๋ฐ์ ์์ผ์ ๋ค์ง์ผ๋ฉด,
์ด๋ ๊ฒ ๋๊ฒ ์ฃ ? ํ์ง๋ง ์์ง head ์ tail์ ์ด์ ์ํ์ ์๋์ ๊ฐ๋ฆฌํค๊ณ ์๊ธฐ ๋๋ฌธ์ ์ด๋๋ก ์ถ๋ ฅ์ ํ๋ฉด 1๋ฒ ๋ ธ๋๋ฅผ ์ถ๋ ฅํ ์ดํ์ ๊ณง๋ฐ๋ก nil์ด ๋ฐํ๋ฉ๋๋ค. head ์ tail๋ ๊ตํํด์ค์๋ค!
์ด์ ์๋ฒฝํ๊ฒ ๋ค์ง์ด์ง ๋งํฌ๋ ๋ฆฌ์คํธ๊ฐ ๋์์ต๋๋ค!
์ ๊ณผ์ ์ ๋ํ ๊ตฌํ์ ์ด๋ ์ต๋๋ค.
mutating func reverse() {
var now = head
while now != nil {
let nowNext = now?.next
now?.next = now?.prev
now?.prev = nowNext
now = now?.prev
}
let nowHead = self.head
self.head = self.tail
self.tail = nowHead
}
์ ์ฒด ์ฝ๋
์๋ฃ๊ตฌ์กฐ ์๋ฆฌ์ฆ์ ์ฝ๋๋ค์ ์ด ๋ ํฌ์์ ๋ชจ๋ ํ์ธํ ์ ์์ด์!
'๐ฎ ์จ-์์ค > ๐ฆด ์๋ฃ๊ตฌ์กฐ' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
๋๊ธ
์ด ๊ธ ๊ณต์ ํ๊ธฐ
-
๊ตฌ๋
ํ๊ธฐ
๊ตฌ๋ ํ๊ธฐ
-
์นด์นด์คํก
์นด์นด์คํก
-
๋ผ์ธ
๋ผ์ธ
-
ํธ์ํฐ
ํธ์ํฐ
-
Facebook
Facebook
-
์นด์นด์ค์คํ ๋ฆฌ
์นด์นด์ค์คํ ๋ฆฌ
-
๋ฐด๋
๋ฐด๋
-
๋ค์ด๋ฒ ๋ธ๋ก๊ทธ
๋ค์ด๋ฒ ๋ธ๋ก๊ทธ
-
Pocket
Pocket
-
Evernote
Evernote