๊ธ€ ์ž‘์„ฑ์ž: ๊ฐœ๋ฐœํ•˜๋Š” ํ›ˆ์ด

๋งํฌ๋“œ ๋ฆฌ์ŠคํŠธ (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
    }

 

์ „์ฒด์ฝ”๋“œ

 

 

GitHub - jeonyeohun/Data-Structures-In-Swift: ๐Ÿ‘ท๐Ÿป‍โ™‚๏ธ STL ์™œ ์—†์–ด.. ์Šค์œ„ํ”„ํŠธ๋กœ ๊ตฌํ˜„ํ•˜๋Š” ์ž๋ฃŒ๊ตฌ์กฐ

๐Ÿ‘ท๐Ÿป‍โ™‚๏ธ STL ์™œ ์—†์–ด.. ์Šค์œ„ํ”„ํŠธ๋กœ ๊ตฌํ˜„ํ•˜๋Š” ์ž๋ฃŒ๊ตฌ์กฐ. Contribute to jeonyeohun/Data-Structures-In-Swift development by creating an account on GitHub.

github.com

์ž๋ฃŒ๊ตฌ์กฐ ์‹œ๋ฆฌ์ฆˆ์˜ ์ฝ”๋“œ๋“ค์€ ์ด ๋ ˆํฌ์—์„œ ๋ชจ๋‘ ํ™•์ธํ•  ์ˆ˜ ์žˆ์–ด์š”!