자료ꡬ쑰

[Swift] 자료ꡬ쑰 - 단방ν–₯ / μ–‘λ°©ν–₯ μ—°κ²° 리슀트(Linked List)

κ²½ν‘Έ 2022. 4. 20. 21:00
λ°˜μ‘ν˜•

μ•ˆλ…•ν•˜μ„Έμš”~

 

μ˜€λŠ˜μ€ 큐에 μ΄μ–΄μ„œ μ—°κ²°λ¦¬μŠ€νŠΈμ— λŒ€ν•΄μ„œ μ •λ¦¬ν•˜λ €κ³  ν•©λ‹ˆλ‹€ : )

 

[ Queue ν¬μŠ€νŒ… ]

 

[Swift] 자료ꡬ쑰 - 큐(Queue)

μ•ˆλ…•ν•˜μ„Έμœ ~ [Swift] 자료ꡬ쑰 - μŠ€νƒ(Stack) μ•ˆλ…•ν•˜μ„Έμœ ~ μ˜€λŠ˜μ€ 자료ꡬ쑰 μ€‘μ—μ„œ μŠ€νƒμ— λŒ€ν•΄μ„œ μ •λ¦¬ν•΄λ³ΌκΉŒ ν•©λ‹ˆλ‹€! 사싀 이전에 ν•™μŠ΅μ„ ν–ˆμ§€λ§Œ μžλ£Œκ΅¬μ‘°μ™€ μ•Œκ³ λ¦¬μ¦˜μ΄ κ°€λ¬Όκ°€λ¬Όν•΄μ§€λŠ”.. κ·Έλž˜μ„œ C

pooh-footprints.tistory.com

 

 


 

μ—°κ²°λ¦¬μŠ€νŠΈκ°€ ν•„μš”ν•œ 이유

μ—°κ²°λ¦¬μŠ€νŠΈλ₯Ό μ‚¬μš©ν•˜λŠ” μ΄μœ λŠ” μ—¬λŸ¬ 가지가 μžˆκ² μ§€λ§Œ 

λ°°μ—΄κ³Ό λΉ„κ΅ν•˜λ©΄μ„œ μ„€λͺ…ν•΄λ³΄κ² μŠ΅λ‹ˆλ‹€.

 

배열은 μž„μ˜ μ ‘κ·Ό(Random Acess)이 κ°€λŠ₯ν•˜κΈ° λ•Œλ¬Έμ—

인덱슀λ₯Ό 톡해 값에 λ°”λ‘œ μ ‘κ·Όν•  수 μžˆμŠ΅λ‹ˆλ‹€.

 

ν•˜μ§€λ§Œ μ‚½μž…, μ‚­μ œμ˜ κ²½μš°μ—λŠ” 

배열을 μž¬λ°°μΉ˜ν•΄μ•Ό ν•˜λŠ” 둜직이 μΆ”κ°€λ˜κ²Œ λ©λ‹ˆλ‹€.

 

예λ₯Ό λ“€μ–΄ λ‹€μŒκ³Ό 같은 배열이 μžˆλ‹€κ³  κ°€μ •ν•΄ λ΄…μ‹œλ‹€.

 

μ›μ†Œ 1 3 5 7
인덱슀 0 1 2 3

 

μ—¬κΈ°μ„œ 0번째 인덱슀λ₯Ό μ œκ±°ν•˜κ²Œ 되면 μ–΄λ–»κ²Œ λ κΉŒμš”?

 

μ›μ†Œ ? 3 5 7
인덱슀 0 1 2 3

 

μœ„μ™€ 같이 0번째 μΈλ±μŠ€μ—λŠ” μ•„λ¬΄λŸ° 값도 μ—†κ²Œ λ©λ‹ˆλ‹€. 

λ”°λΌμ„œ μž¬λ°°μΉ˜κ³Όμ •μ΄ ν•„μš”ν•˜κ²Œ λ˜λŠ” 것이죠.

 

이런 λΆˆνŽΈν•¨μ„ λ³΄μ•ˆν•˜κΈ° μœ„ν•΄μ„œ μ‚¬μš©ν•˜λŠ” 것이 μ—°κ²° 리슀트라고 μƒκ°ν•˜μ‹œλ©΄ λ©λ‹ˆλ‹€.

 

단방ν–₯ μ—°κ²° 리슀트

 

μœ„μ˜ κ·Έλ¦Όμ—μ„œ ν•˜λ‚˜μ˜ λ…Έλ“œκ°€ λ‹€λ₯Έ λ…Έλ“œλ₯Ό 가리킀고 μžˆλŠ” 게 보이싀 κ²λ‹ˆλ‹€.

그리고 λ§ˆμ§€λ§‰ λ…Έλ“œλŠ” λ‹€μŒ λ…Έλ“œκ°€ 없기에 nli둜 μ²˜λ¦¬ν•˜κ²Œ λ©λ‹ˆλ‹€.

이λ₯Ό 단방ν–₯으둜 μ—°κ²°λœ 리슀트라고 ν•©λ‹ˆλ‹€.

λ…Έλ“œ(node)λž€ λ¦¬μŠ€νŠΈμ—μ„œ 데이터λ₯Ό μ €μž₯ν•˜λŠ” λ‹¨μœ„λ‘œ 데이터와 이전, 이후 ν˜Ήμ€ 두 λ°©ν–₯의 λ…Έλ“œλ₯Ό κ°€λ¦¬ν‚€λŠ” ν¬μΈν„°λ‘œ 이루어진 κ°μ²΄μž…λ‹ˆλ‹€.

 

μ—¬κΈ°μ„œ A데이터λ₯Ό μ œκ±°ν•œλ‹€κ³  ν•˜λ©΄ 

λ°”λ‘œ Head ν¬μΈν„°λ§Œ B둜 λ„˜κ²¨μ£Όλ©΄ λ©λ‹ˆλ‹€.

λ¬Όλ‘  Aλ…Έλ“œλŠ” λ©”λͺ¨λ¦¬ν•΄μ œλ₯Ό ν•΄μ£Όμ–΄μ•Ό ν•˜κ³ μš”.

 

μž¬λ°°μΉ˜κ°€ ν•„μš”ν•˜μ§€ μ•ŠμœΌλ‹ˆ

λ°°μ—΄λ³΄λ‹€λŠ” μ‚½μž…ν•˜κ±°λ‚˜ μ‚­μ œν•  λ•Œ μ‹œκ°„λ³΅μž‘λ„ μΈ‘λ©΄μ—μ„œ 이득을 μ·¨ν•  수 있게 λ˜λŠ” κ²ƒμž…λ‹ˆλ‹€.

 

 


 

λ…Έλ“œμ™€ μ–‘λ°©ν–₯ μ—°κ²° 리슀트 κ΅¬ν˜„

- μœ„μ—μ„œ 단방ν–₯ μ—°κ²°λ¦¬μŠ€νŠΈλ₯Ό μ†Œκ°œν–ˆλŠ”λ° μ–‘λ°©ν–₯ 리슀트의 κ²½μš°μ—λŠ” λ‹€μŒμ΄ μ•„λ‹Œ 이전을 κ°€λ¦¬ν‚€λŠ” λ…Έλ“œλ„ μ‘΄μž¬ν•©λ‹ˆλ‹€. 이름 κ·ΈλŒ€λ‘œ μ•ž, λ’€ μ–‘μͺ½ λ°©ν–₯ λͺ¨λ‘λ₯Ό μ•Œ 수 있게 λ˜λŠ” κ²ƒμž…λ‹ˆλ‹€..

 

1. λ…Έλ“œ(Node)

// λ…Έλ“œ
class Node<T> {
    // λ…Έλ“œμ—λŠ” 데이터와 μ•ž, λ’€λ₯Ό κ°€λ₯΄ν‚€λŠ” λ…Έλ“œκ°€ 쑴재!
    var prev: Node?
    var data: T? 
    var next: Node?
    
    init(data: T?, prev: Node? = nil, next: Node? = nil) {
        self.prev = prev
        self.data = data
        self.next = next
    }
}

 

- μ–‘λ°©ν–₯ μ—°κ²°λ¦¬μŠ€νŠΈμ—μ„œμ˜ λ…Έλ“œλŠ” μœ„μ™€ 같이 이전과 이후λ₯Ό κ°€λ₯΄ν‚€λŠ” prev, next κ°€ μ‘΄μž¬ν•©λ‹ˆλ‹€.

 

2. μ–‘λ°©ν–₯ μ—°κ²° 리슀트(Linked List)

- μ—°κ²°λ¦¬μŠ€νŠΈλŠ” λ©”λͺ¨λ¦¬ κ³΅κ°„μ—μ„œ 데이터듀을 μ—°κ²°ν•΄ μ£ΌλŠ” 자료ꡬ쑰이기 λ•Œλ¬Έμ— μ–‘λ°©ν–₯ μ—°κ²°λ¦¬μŠ€νŠΈμ—μ„œλŠ” κ°€μž₯ μ•žμ˜ λ…Έλ“œλ₯Ό κ°€λ₯΄ν‚€λŠ” head와 κ°€μž₯ 뒀에 λ…Έλ“œλ₯Ό κ°€λ₯΄ν‚€λŠ” tail λ…Έλ“œκ°€ μžˆμ–΄μ•Όν•©λ‹ˆλ‹€.  μ΄λŠ” μž„μ˜ 접근이 κ°€λŠ₯ν–ˆλ˜ λ°°μ—΄κ³Ό λ‹€λ₯΄κ²Œ 순차 접근을 ν•΄μ•Όν•˜λŠ” μ΄μœ μ΄κΈ°λ„ ν•©λ‹ˆλ‹€.

 

λ”°λΌμ„œ λ‹€μŒκ³Ό 같이 λ§Œλ“€ 수 μžˆμŠ΅λ‹ˆλ‹€.

// μ—°κ²° 리슀트
class LinkedList<T> {
    // μ—°κ²°λ¦¬μŠ€νŠΈμ˜ 첫번째 λ…Έλ“œλ₯Ό κ°€λ₯΄ν‚€λŠ” head ν”„λ‘œνΌν‹°
    var head: Node<T>?
    // μ—°κ²°λ¦¬μŠ€νŠΈμ˜ λ§ˆμ§€λ§‰ λ…Έλ“œλ₯Ό κ°€λ₯΄ν‚€λŠ” tail ν”„λ‘œνΌν‹°
    var tail: Node<T>?
    
    init(head: Node<T>? = nil, tail: Node<T>? = nil) {
    	self.head = head
        self.tail = tail
    }
}

데이터λ₯Ό μΆ”κ°€ν•˜κ³  μ‚­μ œν•˜κ³  νƒμƒ‰ν•˜λŠ” λ°©λ²•κΉŒμ§€ μ•Œμ•„λ΄…μ‹œλ‹€.

 

3.  μ—°κ²° 리슀트의 크기, 탐색,  μ‚½μž…, μ‚­μ œ

3.1 크기

- μ—°κ²° 리슀트의 크기 즉, λ°μ΄ν„°μ˜ 개수λ₯Ό κ΅¬ν•˜λŠ” λ©”μ„œλ“œμž…λ‹ˆλ‹€.

- λ§ˆμ§€λ§‰ λ…Έλ“œμ˜ 경우 λ‹€μŒ 데이터λ₯Ό κ°€λ₯΄ν‚€λŠ” λ…Έλ“œκ°€ μ—†μœΌλ―€λ‘œ nil인 점을 μ΄μš©ν•΄ μ‚¬μ΄μ¦ˆλ₯Ό 확인할 수 μžˆμŠ΅λ‹ˆλ‹€.

 

func size() -> Int {
    // λ…Έλ“œκ°€ μ‘΄μž¬ν•˜λŠ”μ§€!
    guard var node = self.head else {
        return 0
    }
    var count = 0
    // λ§ˆμ§€λ§‰ λ…Έλ“œλŠ” nil을 가지고 μžˆλŠ” 것을 ν™œμš©ν•΄
    // 탐색 및 개수λ₯Ό 카운트 ν•©λ‹ˆλ‹€!
    while node.next != nil {
        count += 1
        node = node.next!
    }
    return count
}

3.2 탐색

- μ—°κ²° 리슀트의 크기λ₯Ό κ΅¬ν•˜λ©΄μ„œ 이걸 μ΄μš©ν•˜λ©΄ νŠΉμ •ν•œ μˆœμ„œμ˜ λ…Έλ“œλ₯Ό 확인할 수 μžˆκ² λ‹€κ³  μƒκ°ν–ˆμ„ 수 μžˆμŠ΅λ‹ˆλ‹€. κ·Έ 점을 μ΄μš©ν•΄μ„œ λ‹€μŒκ³Ό 같이 확인할 수 μžˆμŠ΅λ‹ˆλ‹€.

func findNode(at index: Int) -> Node<T>? {
    guard var node = self.head else {
        return nil
    }
    // index에 ν•΄λ‹Ήν•˜λŠ” κ°’κΉŒμ§€ λ°˜λ³΅ν•΄μ„œ λ‹€μŒ λ…Έλ“œλ‘œ 탐색
    for _ in 1...index {
        guard let nextNode = node.next else {
            return nil
        }
        node = nextNode
    }
    return node
}

- λ°˜λŒ€λ‘œ νŠΉμ •ν•œ 값을 가지고 μžˆλŠ” λ…Έλ“œλ„ μ°Ύμ•„λ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€.

func firstIndex(of data: T) -> Int? {
    guard var node = self.head else {
        return nil
    }
    var count = 0
    while true {
        // νŠΉμ •ν•œ λ°μ΄ν„°μ˜ 값을 가지고 μžˆλŠ” λ…Έλ“œκ°€
        // λͺ‡λ²ˆμ§Έμ— μžˆλŠ”μ§€ 확인 ν›„ λ°˜ν™˜!
        if node.data == data {
            return count
        }
        guard let next = node.next else {
            return nil
        }
        node = next
        count += 1
    }
}

 

μ€‘μš” : μœ„μ—μ„œ node.data = dataμ—μ„œ 였λ₯˜κ°€ λ°œμƒν•©λ‹ˆλ‹€. λ°”λ‘œ μ œλ„€λ¦­μ˜ 경우 "==" μ—°μ‚°μžλ₯Ό μ‚¬μš©ν•  수 μ—†κΈ° λ•Œλ¬ΈμΈλ° 기쑴의 LinkedList ν΄λž˜μŠ€μ—μ„œ LinkedList <T: Equatable>둜 λ°”κΎΈμ–΄μ•Ό μ‚¬μš©ν•  수 있게 λ©λ‹ˆλ‹€.

 

3.3 μΆ”κ°€

- μƒˆλ‘­κ²Œ μƒμ„±λœ λ…Έλ“œμ™€ μ›ν•˜λŠ” μœ„μΉ˜λ₯Ό μž…λ ₯λ°›κ³  μ•žμ˜ λ…Έλ“œμ™€ λ’€μ˜ λ…Έλ“œμ˜ 유무λ₯Ό νŒλ³„ν•œ λ‹€μŒ μ—°κ²°ν•΄μ£ΌλŠ” λ©”μ„œλ“œμž…λ‹ˆλ‹€. μžμ„Έν•œ λ‚΄μš©μ€ 주석을 톡해 μž…λ ₯ν•΄ λ‘μ—ˆμŠ΅λ‹ˆλ‹€.

func insert(_ newNode: Node<T>, at index: Int) {
    // headκ°€ nil이라면 아직 아무것도 μ—†λ‹€λŠ” κ±°κ² μ£ ?
    // λ”°λΌμ„œ head와 tail에 μƒˆλ‘œμš΄ λ…Έλ“œ(newNode)λ₯Ό μ €μž₯ν•΄ μ£Όλ©΄ λ©λ‹ˆλ‹€! 
    if self.head == nil {
        self.head = newNode
        self.tail = newNode
        return
    }

    // λ§Œμ•½μ— μ•žμ˜ λ…Έλ“œλ₯Ό 찾을 수 μ—†λ‹€λ©΄ 즉, 기쑴의 μ—°κ²° 리슀트의 길이보닀 κΈ΄
    // 인덱슀 값이 λ“€μ–΄μ˜€κ²Œ 된 것 이기 λ•Œλ¬Έμ— 
    // λΆ„κΈ°μ²˜λ¦¬ν•˜κ±°λ‚˜ κ°€μž₯ 뒀에 λΆ™μ—¬μ£Όλ©΄ λ©λ‹ˆλ‹€μœ  / μ—¬κΈ°μ„œλŠ” κ°€μž₯ 뒀에 λΆ™μ—¬μ€¬μŠ΅λ‹ˆλ‹Ή
    guard let prevNode = findNode(at: index-1) else {
        self.tail?.next = newNode 
        self.tail = newNode
        return
    }
	
    guard let nextNode = prevNode.next else {
    	// prevNode λ‹€μŒμ΄ nil이라면 tail이되기 λ•Œλ¬Έμ— λ°”λ‘œ λ‹€μŒμœΌλ‘œ μ—°κ²°!
        prevNode.next = newNode
        self.tail = newNode
        return
    }
    
    /*
    μœ„μ˜ 과정을 λͺ¨λ‘ κ±°μ³€λ‹€λ©΄
    newNode의 λ‹€μŒμ€ nextNodeκ°€ 되고
    prevNode(ν•˜λ‚˜ 이전)의 λ‹€μŒμ€ newNodeκ°€ λœλ‹€.
    prevNode -> nextNode μ˜€λ˜ μ—°κ²°λ¦¬μŠ€νŠΈμ—μ„œ ν•΄λ‹Ή μΈλ±μŠ€μ— λ“€μ–΄μ˜€λ‹ˆ
    이 두 λ…Έλ“œ μ‚¬μ΄μ˜€κ³ 
    즉, prevNode -> newNode -> nextNodeκ°€ λ˜λŠ” 것!
    */
    newNode.next = nextNode
    prevNode.next = newNode
}

 

3.4 μ‚­μ œ

- μ‚½μž…κ³Ό 과정이 λΉ„μŠ·ν•©λ‹ˆλ‹€. μ΄μ „μ˜ λ…Έλ“œλ₯Ό μ°Ύκ³  μ‹œμž‘ν•˜μ‹œλ©΄ λ©λ‹ˆλ‹€.

func remove(at index: Int) {
    // prevNodeκ°€ μ—†λ‹€λ©΄? 즉, μ΄μ „μ˜ λ…Έλ“œκ°€ μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ” λ‹€λŠ” 말!
    // λ”°λΌμ„œ ν• κ²Œ μ—†μŠ΅λ‹ˆλ‹Ή..
    guard let prevNode = findNode(at: index-1) else {
        return
    }

    // prevNodeκ°€ λ§ˆμ§€λ§‰ λ…Έλ“œλΌλ©΄ μœ„μ™€ λ§ˆμ°¬κ°€μ§€κ² μ£ !
    // ν• κ²Œ μ—†μŠ΅λ‹ˆλ‹Ή..
    guard let removeNode = prevNode.next else {
        return
    }

    // index μœ„μΉ˜μ˜ λ…Έλ“œ(removeNode)κ°€ λ§ˆμ§€λ§‰ λ…Έλ“œλΌλ©΄?
    // μ΄μ „μ˜ λ…Έλ“œκ°€ κ°€λ₯΄ν‚¬ 것은 μ—†μœΌλ‹ˆ nil
    // tail의 κ²½μš°μ—λŠ” μ΄μ „μ˜ λ…Έλ“œλ₯Ό κ°€λ₯΄ν‚€κ³  μžˆμ–΄μ•Όκ² μ₯¬!
    guard let nextNode = removeNode.next else {
        prevNode.next = nil
        self.tail = prevNode
        return
    }

    // index μœ„μΉ˜μ˜ λ…Έλ“œ(removeNode)κ°€ λ§ˆμ§€λ§‰ λ…Έλ“œκ°€ μ•„λ‹ˆλΌλ©΄?
    // λ‹Ήμ—°νžˆ μ΄μ „μ˜ λ…Έλ“œ λ‹€μŒλ…Έλ“œκ°€ 제거될 λ…Έλ“œμ˜ λ‹€μŒ λ…Έλ“œλ₯Ό κ°€λ₯΄ν‚€λŠ”!!
    // 즉, prevtNode -> removeNode -> nextNode μƒνƒœμ—μ„œ
    // removeNodeκ°€ 제거 되게 ν•˜λ €λ©΄
    // prevNode.next = nextNodeκ°€ λ˜μ•Όν•˜λŠ” 것!
    prevNode.next = nextNode
}

 

 

λ‹€μŒ ν¬μŠ€νŒ…μ€ ν•΄μ‹œ ν…Œμ΄λΈ”μž…λ‹ˆλ‹€.

 

 

[Swift] 자료ꡬ쑰 - ν•΄μ‹œ ν…Œμ΄λΈ”(Hash Table)

μ•ˆλ…•ν•˜μ„Έμœ ~ μ˜€λŠ˜μ€ μ—°κ²° λ¦¬μŠ€νŠΈμ— μ΄μ–΄μ„œ ν•΄μ‹œ ν…Œμ΄λΈ”μ„ μ •λ¦¬ν•˜λŠ” μ‹œκ°„μ„ κ°€μ Έλ³ΌκΉŒν•©λ‹ˆλ‹Ήγ…Žγ…Ž [Swift] 자료ꡬ쑰 - μ—°κ²° 리슀트(Linked List)(1) μ•ˆλ…•ν•˜μ„Έμœ ~ μ˜€λŠ˜μ€ μ €λ²ˆ κ²Œμ‹œλ¬Όμ—μ„œ λ§ν–ˆλ˜ κ²ƒμ²˜λŸΌ

pooh-footprints.tistory.com

 

그럼 이만 πŸ‘‹πŸ» πŸ‘‹πŸ» πŸ‘‹πŸ»

 


 

μ°Έκ³ ν•œ λ§ν¬λ“€μž…λ‹ˆλ‹€.

κ°μ‹œν•©λ‹ˆλ‹€ πŸ‘

 

Swift) 단방ν–₯ μ—°κ²° 리슀트(LinkedList) κ΅¬ν˜„ 해보기

μ•ˆλ…•ν•˜μƒˆμš” :) μ†Œλ“€μž…λ‹ˆλ‹€! μ˜€λŠ˜μ€ μ—°κ²° λ¦¬μŠ€νŠΈμ— λŒ€ν•΄ 곡뢀해보렀고 ν•΄μš”!!!! πŸ€ͺ κ·Έ μ€‘μ—μ„œλ„ 이번 ν¬μŠ€νŒ…μ—μ„  단방ν–₯에 λŒ€ν•΄ λ‹€λ£° κ²ƒμž…λ‹ˆλ‹€..! μ œκ°€ μ˜›~~날에 자료ꡬ쑰 μˆ˜μ—… 듀을 λ•Œ 되게 재밌

babbab2.tistory.com

 

[Linked List μ—°κ²°λ¦¬μŠ€νŠΈ] λ°°μ—΄κ³Όμ˜ 차이점 / 그리고 Swift둜 κ΅¬ν˜„ 해보기

λ°°μ—΄μ΄λž€? (Array) ν”„λ‘œκ·Έλž˜λ°μ—μ„œ 데이터 값을 μ €μž₯ν•˜λŠ” 곡간을 λ³€μˆ˜λΌκ³  λΆ€λ₯Έλ‹€. 독립적인 ν•œ 개의 κ°’λ§Œ μ €μž₯ν•  λ•ŒλŠ” λ³€μˆ˜λ₯Ό μ‚¬μš©ν•˜μ§€λ§Œ, μ—°κ΄€λœ 데이터λ₯Ό ν•œκΊΌλ²ˆμ— λ¬Άμ–΄μ„œ μ €μž₯ν•  λ•ŒλŠ” 주둜 λ°°

tngusmiso.tistory.com

 

λ°˜μ‘ν˜•