πŸ’» Programming 개발/🍎 iOS 개발, Swift

[Swift][λ²ˆμ—­] μŠ€μœ„ν”„νŠΈμ˜ μžλ£Œκ΅¬μ‘°μ™€ μ•Œκ³ λ¦¬μ¦˜ - μ„Ήμ…˜ 2. 기초 자료ꡬ쑰 - 챕터6-1. μ—°κ²°λ¦¬μŠ€νŠΈ (μ •μ˜, μ‚½μž…, μ‚­μ œ)

kimdee 2022. 5. 30. 10:31
λ°˜μ‘ν˜•

[Swift][λ²ˆμ—­] μŠ€μœ„ν”„νŠΈμ˜ μžλ£Œκ΅¬μ‘°μ™€ μ•Œκ³ λ¦¬μ¦˜ - μ„Ήμ…˜ 2. 기초 자료ꡬ쑰 - 챕터6-1. μ—°κ²°λ¦¬μŠ€νŠΈ 

Raywenderlich.com μ—μ„œ λ‚˜μ˜¨ Data Structures & Algorithms in Swift μ±…μ˜ 데λͺ¨ κ³΅κ°œλ³Έμ„ λ²ˆμ—­ν•˜μ˜€μŠ΅λ‹ˆλ‹€. 즐겁게 λ΄μ£Όμ„Έμš”. 

https://www.raywenderlich.com/books/data-structures-algorithms-in-swift

 

 


 

μ„Ήμ…˜ 2. 기초 자료ꡬ쑰 Elementary Data Structure

챕터 6. μ—°κ²° 리슀트 Linked Lists 

μ—°κ²°λ¦¬μŠ€νŠΈλŠ” 값듀이 μ„ ν˜•μ μ΄κ³  일방ν–₯적인 μ‹œν€€μŠ€λ‘œ 배치된 μ½œλ ‰μ…˜μž…λ‹ˆλ‹€. μ—°κ²°λ¦¬μŠ€νŠΈλŠ” μŠ€μœ„ν”„νŠΈ λ°°μ—΄κ³Ό 같은 연속저μž₯ μ˜΅μ…˜μ— λΉ„ν•΄ 이둠적인 μš°μœ„λ₯Ό 가지고 μžˆμŠ΅λ‹ˆλ‹€.

  • 리슀트의 μ•žλΆ€λΆ„μ—μ„œ μ‚½μž… μ‚­μ œλŠ” μƒμˆ˜μ‹œκ°„(constant time)이 κ±Έλ¦Ό
  • μ‹ λ’°ν•  수 μžˆλŠ” μ„±λŠ₯ νŠΉμ„±

 

 

 

μœ„ λ‹€μ΄μ–΄κ·Έλž¨μ—μ„œ λ³΄μ΄λŠ” κ²ƒμ²˜λŸΌ μ—°κ²°λ¦¬μŠ€νŠΈλŠ” λ…Έλ“œλ“€μ˜ μ²΄μΈμž…λ‹ˆλ‹€. λ…Έλ“œμ—λŠ” 두가지 μ˜λ¬΄κ°€ μžˆμŠ΅λ‹ˆλ‹€.

  1. 값을 보유
  2. λ‹€μŒ λ…Έλ“œμ˜ 레퍼런슀λ₯Ό 보유. λ‹€μŒ λ…Έλ“œ λ ˆνΌλŸ°μŠ€κ°€ nil 일 경우 리슀트의 끝을 의미

이번 μ±•ν„°μ—μ„œλŠ” μ—°κ²°λ¦¬μŠ€νŠΈλ₯Ό κ΅¬ν˜„ν•˜κ³  μ—°κ²°λ¦¬μŠ€νŠΈμ™€ κ΄€λ ¨λœ 일반적인 μž‘μ—…μ— λŒ€ν•΄ 배울 κ²ƒμž…λ‹ˆλ‹€. 각 μž‘μ—…μ˜ μ‹œκ°„ λ³΅μž‘λ„λ₯Ό 배우고 μŠ€μœ„ν”„νŠΈμ˜ 멋진 κΈ°λŠ₯인 Copy On Write(COW, μ•”μ‹œμ  곡유) 을 κ΅¬ν˜„ν•  κ²ƒμž…λ‹ˆλ‹€.

이번 μ±•ν„°μ˜ μŠ€νƒ€ν„° ν”Œλ ˆμ΄κ·ΈλΌμš΄λ“œλ₯Ό μ—΄μ–΄ μ½”λ“œλ‘œ λΉ μ Έλ΄…μ‹œλ‹€.

 

 

 


 

λ…Έλ“œ Node

Sources 디렉토리에 Node.swift 을 μƒμ„±ν•˜κ³  μ•„λž˜ μ½”λ“œλ₯Ό νŒŒμΌμ— μΆ”κ°€ν•©λ‹ˆλ‹€.

public class Node<Value> {

  public var value: Value
  public var next: Node?

  public init(value: Value, next: Node? = nil) {
    self.value = value
    self.next = next
  }
}

extension Node: CustomStringConvertible {

  public var description: String {
    guard let next = next else {
      return "\(value)"
    }
    return "\(value) -> " + String(describing: next) + " "
  }
}

ν”Œλ ˆμ΄κ·ΈλΌμš΄λ“œ νŽ˜μ΄μ§€λ‘œ μ΄λ™ν•˜μ—¬ λ‹€μŒμ„ μΆ”κ°€ν•©λ‹ˆλ‹€.

 

example(of: "creating and linking nodes") {
  let node1 = Node(value: 1)
  let node2 = Node(value: 2)
  let node3 = Node(value: 3)

  node1.next = node2
  node2.next = node3

  print(node1)
}

μ—¬λŸ¬λΆ„μ€ 방금 μ„Έκ°œμ˜ λ…Έλ“œλ₯Ό λ§Œλ“€κ³  이듀을 μ—°κ²°ν•˜μ˜€μŠ΅λ‹ˆλ‹€.

 

1,2,3 값을 가지고 μžˆλŠ” μ—°κ²°λ¦¬μŠ€νŠΈ

μ½˜μ†” μ°½μ—μ„œ μ•„λž˜ 아웃풋을 λ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€.

---Example of creating and linking nodes---
1 -> 2 -> 3

리슀트λ₯Ό λ§Œλ“œλŠ” 이 방법은 μ‹€μš©μ„±μ— κ΄€ν•΄μ„œλŠ” 아직 많이 λΆ€μ‘±ν•©λ‹ˆλ‹€. 이 λ°©λ²•μœΌλ‘œ κΈ΄ 리슀트λ₯Ό λ§Œλ“ λ‹€λ©΄ μ‹€μš©μ μ΄μ§€ λͺ»ν•œ 것을 λ°”λ‘œ μ•Œ 수 μžˆμ„ κ²ƒμž…λ‹ˆλ‹€. 이 문제λ₯Ό μ€„μ΄λŠ” 일반적인 방법은 LinkedList λ₯Ό λΉŒλ“œν•΄μ„œ Node 였브젝트λ₯Ό κ΄€λ¦¬ν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€. κ·Έλƒ₯ ν•˜λ©΄ λ©λ‹ˆλ‹€.

 

 

 

μ—°κ²°λ¦¬μŠ€νŠΈ LinkedList

LinkedList.swift λ₯Ό μƒμ„±ν•˜κ³  μ•„λž˜λ₯Ό νŒŒμΌμ— μΆ”κ°€ν•©λ‹ˆλ‹€.

public struct LinkedList<Value> {

  public var head: Node<Value>?
  public var tail: Node<Value>?

  public init() {}

  public var isEmpty: Bool {
    head == nil
  }
}

extension LinkedList: CustomStringConvertible {

  public var description: String {
    guard let head = head else {
      return "Empty list"
    }
    return String(describing: head)
  }
}

λ§ν¬λ“œλ¦¬μŠ€νŠΈλŠ” head 와 tail μ΄λΌλŠ” κ°œλ…μ΄ μžˆμŠ΅λ‹ˆλ‹€. 각각 리슀트의 첫번째 λ…Έλ“œμ™€ λ§ˆμ§€λ§‰ λ…Έλ“œλ₯Ό μ˜λ―Έν•©λ‹ˆλ‹€.

 

 

 

 

λ¦¬μŠ€νŠΈμ— κ°’(μš”μ†Œ) μΆ”κ°€ν•˜κΈ°

μ•žμ„œ μ–ΈκΈ‰ν•œ 바와 같이, Node 개체λ₯Ό κ΄€λ¦¬ν•˜λŠ” μΈν„°νŽ˜μ΄μŠ€κ°€ μ œκ³΅λ©λ‹ˆλ‹€. λ¨Όμ € μš”μ†Œλ₯Ό μΆ”κ°€ν•΄λ΄…μ‹œλ‹€. μ—°κ²°λ¦¬μŠ€νŠΈμ— 값을 μΆ”κ°€ν•˜λŠ” λ°λŠ” 각각 λ‹€λ₯Έ μ„±λŠ₯ νŠΉμ„±μ„ 가지고 μžˆλŠ” 3가지 방법이 μžˆμŠ΅λ‹ˆλ‹€.

  1. push: 값을 리슀트 μ•žμ— μΆ”κ°€ν•˜κΈ°
  2. append: 값을 리슀트 끝에 μΆ”κ°€ν•˜κΈ°γ…£
  3. insert(after:): 값을 νŠΉμ • λ…Έλ“œ λ‹€μŒμ— μΆ”κ°€ν•˜κΈ°

μ•žμœΌλ‘œ μš°λ¦¬λŠ” 이 세가지λ₯Ό λ‹€μŒ μ„Ήμ…˜μ—μ„œ κ΅¬ν˜„ν•΄λ³΄κ³  각각의 μ„±λŠ₯νŠΉμ„±μ„ 뢄석할 κ²ƒμž…λ‹ˆλ‹€.

 

 

ν‘Έμ‹œ μž‘μ—… push operations

리슀트의 맨 μ•žμ— 값을 μΆ”κ°€ν•˜λŠ”  push μž‘업은  head-first insertion 이라고도 ν•©λ‹ˆλ‹€. μ½”λ“œλŠ” ꡉμž₯히 λ‹¨μˆœν•©λ‹ˆλ‹€.

μ•„λž˜ λ©”μ„œλ“œλ₯Ό  LinkedList에 μΆ”κ°€ν•˜μ„Έμš”.

 

public mutating func push(_ value: Value) {
  head = Node(value: value, next: head)
  if tail == nil {
    tail = head
  }
}

빈 λ¦¬μŠ€νŠΈμ— 값을 ν‘Έμ‹œν•˜λ©΄, μƒˆλ‘œμš΄ λ…Έλ“œλŠ” 리슀트의 head 이자 tail 이 λ©λ‹ˆλ‹€.

ν”Œλ ˆμ΄κ·ΈλΌμš΄λ“œμ—μ„œ μ•„λž˜λ₯Ό μΆ”κ°€ν•˜μ„Έμš”.

 

example(of: "push") {
  var list = LinkedList<Int>()
  list.push(3)
  list.push(2)
  list.push(1)

  print(list)
}

 

μ½˜μ†”μ°½μ—μ„œ μ•„λž˜μ™€ 같이 좜λ ₯λ©λ‹ˆλ‹€.

---Example of push---
1 -> 2 -> 3

push μ™€ pop μ€ λ‘˜ λ‹€ μ‹œκ°„λ³΅μž‘λ„κ°€ O(1) μž…λ‹ˆλ‹€.

 

append μž‘μ—…

λ‹€μŒμœΌλ‘œ μ‚΄νŽ΄λ³Ό μž‘μ—…μ€ append μž…λ‹ˆλ‹€. 리슀트의 κ°€μž₯ 끝에 값을 μΆ”κ°€ν•˜λ©°, tail-end insertion 이라고 ν•©λ‹ˆλ‹€.

LinkedList.swift μ—μ„œ μ•„λž˜ μ½”λ“œλ₯Ό  push μ•„λž˜μ— μž…λ ₯ν•˜μ„Έμš”.

 

public mutating func append(_ value: Value) {

  // 1
  guard !isEmpty else {
    push(value)
    return
  }

  // 2
  tail!.next = Node(value: value)

  // 3
  tail = tail!.next
}

 

이 μ½”λ“œλ“€μ€ 비ꡐ적 κ°„λ‹¨ν•©λ‹ˆλ‹€.

  1. 이전에 μ–˜κΈ°ν•œ κ²ƒμ²˜λŸΌ λ¦¬μŠ€νŠΈκ°€ λΉ„μ–΄μžˆλ‹€λ©΄ head 와 tail 을 μƒˆ λ…Έλ“œλ‘œ μ—…λ°μ΄νŠΈ ν•΄μ£Όμ–΄μ•Όν•©λ‹ˆλ‹€. 빈 λ¦¬μŠ€νŠΈμ— append λŠ” κΈ°λŠ₯적으둜 push 와 λ™μΌν•˜λ―€λ‘œ push λ₯Ό ν˜ΈμΆœν•˜μ—¬ μž‘μ—…μ„ μˆ˜ν–‰ν•©λ‹ˆλ‹€.
  2. κ·Έ μ™Έ λͺ¨λ“  경우 μ—¬λŸ¬λΆ„μ€ tail 뒀에 μƒˆ λ…Έλ“œλ₯Ό λ§Œλ“€κ²Œ λ©λ‹ˆλ‹€. guard 문을 μ΄μš©ν•˜μ—¬ isEmpty μΌ€μ΄μŠ€λ₯Ό ν‘Έμ‹œν•˜λ―€λ‘œ λͺ…μ‹œμ  μ–Έλž˜ν•‘μ€ Force unwrapping 은 잘 μˆ˜ν–‰λ©λ‹ˆλ‹€.
  3. tail-end insertion μ΄λ―€λ‘œ μ—¬λŸ¬λΆ„μ˜ μƒˆ λ…Έλ“œλŠ” 리슀트의 tail이 λ©λ‹ˆλ‹€.

ν”Œλ ˆμ΄κ·ΈλΌμš΄λ“œλ‘œ λŒμ•„κ°€μ„œ λ‹€μŒ μ½”λ“œλ₯Ό μ•„λž˜μ— μž‘μ„±ν•©λ‹ˆλ‹€.

example(of: "append") {
  var list = LinkedList<Int>()
  list.append(1)
  list.append(2)
  list.append(3)

  print(list)
}

 

μ•„λž˜ κ²°κ³Όκ°€ μ½˜μ†”μ°½μ—μ„œ 좜λ ₯λ©λ‹ˆλ‹€.

---Example of append---
1 -> 2 -> 3

 

insert(after:) μž‘μ—…

λ¦¬μŠ€νŠΈμ— 값을 μΆ”κ°€ν•˜λŠ” μ„Έλ²ˆμ§Έμ΄μž λ§ˆμ§€λ§‰ μž‘μ—…μ€ insert(after:) μž…λ‹ˆλ‹€. 이 μž‘μ—…μ€ 리슀트의 νŠΉμ • μœ„μΉ˜μ— 값을 μ‚½μž…ν•˜λŠ” μž‘μ—…μœΌλ‘œ 두가지 단계가 ν•„μš”ν•©λ‹ˆλ‹€.

  1. 리슀트의 νŠΉμ • λ…Έλ“œλ₯Ό μ°ΎλŠ”λ‹€.
  2. μƒˆλ‘œμš΄ λ…Έλ“œλ₯Ό μ‚½μž…ν•œλ‹€.

λ¨Όμ € 값을 μ‚½μž…ν•˜κ³ μž ν•˜λŠ” λ…Έλ“œλ₯Ό μ°ΎλŠ” μ½”λ“œλ₯Ό κ΅¬ν˜„ν•©λ‹ˆλ‹€. LinkedList.swift, μ—μ„œ append μ•„λž˜μ— λ‹€μŒ μ½”λ“œλ₯Ό μΆ”κ°€ν•©λ‹ˆλ‹€.

 

public func node(at index: Int) -> Node<Value>? {
  // 1
  var currentNode = head
  var currentIndex = 0

  // 2
  while currentNode != nil && currentIndex < index {
    currentNode = currentNode!.next
    currentIndex += 1
  }

  return currentNode
}

 

node(at:) μ€ 주어진 μΈλ±μŠ€μ— 따라 리슀트 μ•ˆμ˜ λ…Έλ“œλ₯Ό κ²€μƒ‰ν•©λ‹ˆλ‹€. 리슀트의 λ…Έλ“œλŠ” head λ…Έλ“œμ—μ„œλΆ€ν„°λ°–μ— μ ‘κ·Όν•  수 μ—†μœΌλ―€λ‘œ 반볡적인 순회λ₯Ό ν•΄μ•Όν•©λ‹ˆλ‹€. ν•˜λ‚˜μ”© λ”°λΌκ°€λ΄…μ‹œλ‹€.

  1. head 의 μƒˆλ‘œμš΄ 레퍼런슀λ₯Ό μƒμ„±ν•˜κ³  ν˜„μž¬ μˆœνšŒν•˜κ³  μžˆλŠ” μœ„μΉ˜λ₯Ό μΆ”μ ν•©λ‹ˆλ‹€.
  2. while λ°˜λ³΅λ¬Έμ„ μ΄μš©ν•˜μ—¬ μ›ν•˜λŠ” μΈλ±μŠ€κΉŒμ§€ 리슀트의 μ•„λž«μͺ½μœΌλ‘œ 레퍼런슀λ₯Ό μ΄λ™ν•©λ‹ˆλ‹€. 빈 λ¦¬μŠ€νŠΈμ΄κ±°λ‚˜ 리슀트의 λ²”μœ„λ₯Ό μ΄ˆκ³Όν•˜λŠ” μΈλ±μŠ€λŠ” nil 을 λ°˜ν™˜ν•©λ‹ˆλ‹€.

이제 μƒˆλ‘œμš΄ λ…Έλ“œλ₯Ό μ‚½μž…ν•΄μ•Ό ν•©λ‹ˆλ‹€. μ•„λž˜ λ©”μ„œλ“œλ₯Ό node(at:) μ•„λž˜μ— μΆ”κ°€ν•©λ‹ˆλ‹€.

 

// 1
@discardableResult
public mutating func insert(_ value: Value,
                            after node: Node<Value>)
                            -> Node<Value> {
  // 2
  guard tail !== node else {
    append(value)
    return tail!
  }
  // 3
  node.next = Node(value: value, next: node.next)
  return node.next!
}

μ—¬λŸ¬λΆ„μ΄ ν•œ 것은 λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€.

  1. @discardableResult λŠ” μ»΄νŒŒμΌλŸ¬κ°€ κ²½κ³ ν•˜μ§€ μ•Šκ³ λ„ ν˜ΈμΆœμžκ°€ λ©”μ„œλ“œμ˜ λ°˜ν™˜κ°’μ„ λ¬΄μ‹œν•  수 μžˆμŠ΅λ‹ˆλ‹€.
  2. 이 λ©”μ„œλ“œκ°€ tail λ©”μ„œλ“œμ™€ ν•¨κ»˜ ν˜ΈμΆœλ˜λŠ” 경우 κΈ°λŠ₯적으둜 λ™λ“±ν•œ append λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•˜κ²Œ λ©λ‹ˆλ‹€. μ΄λŠ” tail λ…Έλ“œλ₯Ό μ—…λ°μ΄νŠΈν•©λ‹ˆλ‹€.
  3. κ·Έ μ™Έμ—λŠ” μƒˆ λ…Έλ“œλ₯Ό 리슀트의 λ‚˜λ¨Έμ§€μ™€ μ—°κ²°ν•˜κ³  μƒˆ λ…Έλ“œλ₯Ό λ°˜ν™˜ν•©λ‹ˆλ‹€.

ν”Œλ ˆμ΄κ·ΈλΌμš΄λ“œ νŽ˜μ΄μ§€λ‘œ λŒμ•„κ°€ ν…ŒμŠ€νŠΈν•©λ‹ˆλ‹€. μ•„λž˜ μ½”λ“œλ₯Ό ν”Œλ ˆμ΄κ·ΈλΌμš΄λ“œ μ•„λž˜μ— μΆ”κ°€ν•©λ‹ˆλ‹€.

 

example(of: "inserting at a particular index") {
  var list = LinkedList<Int>()
  list.push(3)
  list.push(2)
  list.push(1)

  print("Before inserting: \(list)")
  var middleNode = list.node(at: 1)!
  for _ in 1...4 {
    middleNode = list.insert(-1, after: middleNode)
  }
  print("After inserting: \(list)")
}

μ•„λž˜ 결과물을 확인할 수 μžˆμŠ΅λ‹ˆλ‹€.

 

---Example of inserting at a particular index---
Before inserting: 1 -> 2 -> 3
After inserting: 1 -> 2 -> -1 -> -1 -> -1 -> -1 -> 3

μ„±λŠ₯평가

 

휴! μ΄μ œκΉŒμ§€ 잘 ν•΄μ™”μŠ΅λ‹ˆλ‹€. μš”μ•½ν•˜λ©΄ μš°λ¦¬λŠ” μ—°κ²°λ¦¬μŠ€νŠΈμ— 값을 μΆ”κ°€ν•˜λŠ” 세가지 μž‘μ—…κ³Ό νŠΉμ • μΈλ±μŠ€μ— μœ„μΉ˜ν•œ λ…Έλ“œλ₯Ό μ°ΎλŠ” λ©”μ„œλ“œλ₯Ό κ΅¬ν˜„ν•˜μ˜€μŠ΅λ‹ˆλ‹€.

 

  push append insert(after:) node(at:)
λ™μž‘ Behaviour head에 μ‚½μž… tail에 μ‚½μž… νŠΉμ • λ…Έλ“œ λ‹€μŒμ— μ‚½μž… 주어진 인덱슀의 λ…Έλ“œλ₯Ό λ°˜ν™˜
μ‹œκ°„λ³΅μž‘λ„ Time complexity O(1) O(1) O(1) O(i), i λŠ” 주어진 인덱슀

 

λ‹€μŒμœΌλ‘œ 이와 λ°˜λŒ€λ˜λŠ” μ‚­μ œ μž‘μ—…μ„ μ‚΄νŽ΄λ΄…μ‹œλ‹€.

 


λ¦¬μŠ€νŠΈμ—μ„œ κ°’(μš”μ†Œ) μ‚­μ œν•˜κΈ°

λ…Έλ“œ μ‚­μ œμ—λŠ” 세가지 λ°©μ‹μ˜ μ£Όμš” μž‘μ—…μ΄ μžˆμŠ΅λ‹ˆλ‹€.

  1. pop: 리슀트 맨 μ•žμ˜ 값을 μ‚­μ œ
  2. removeLast: 리슀트 맨 λ§ˆμ§€λ§‰ 값을 μ‚­μ œ
  3. remove(at:): 리슀트 νŠΉμ • μœ„μΉ˜μ˜ 값을 μ‚­μ œ

μœ„ 세가지λ₯Ό κ΅¬ν˜„ν•˜κ³  μ„±λŠ₯ νŠΉμ„±μ„ ν‰κ°€ν•΄λ΄…μ‹œλ‹€.

 

pop μž‘μ—…

리슀트의 μ•žμ— μžˆλŠ” 값을 μ‚­μ œν•˜λŠ” 것은 pop μž…λ‹ˆλ‹€. 이 μž‘μ—…μ€ push 만큼 κ°„λ‹¨ν•©λ‹ˆλ‹€.λ°”λ‘œ μ‹œμž‘ν•©μ‹œλ‹€.

μ•„λž˜ λ©”μ„œλ“œλ₯Ό  LinkedList 에 μΆ”κ°€ν•©λ‹ˆλ‹€.

@discardableResult
public mutating func pop() -> Value? {
  defer {
    head = head?.next
    if isEmpty {
      tail = nil
    }
  }
  return head?.value
}

pop μ€ λ¦¬μŠ€νŠΈμ—μ„œ μ‚­μ œλ˜λ‹ˆ 값을 반ν™₯ν™˜ν•©λ‹ˆλ‹€. λ¦¬μŠ€νŠΈκ°€ λΉ„μ–΄μžˆμ„ μˆ˜λ„ μžˆμœΌλ―€λ‘œ 이 값은 μ˜΅μ…”λ„μž…λ‹ˆλ‹€.

head λ…Έλ“œλ₯Ό μ•„λž˜λ‘œ μ΄λ™ν•˜μ—¬ 리슀트의 첫번째 λ…Έλ“œλ₯Ό 효과적으둜 μ œκ±°ν•˜μ˜€μŠ΅λ‹ˆλ‹€. ARCλŠ” μ–΄λŠ λ ˆνΌλŸ°μŠ€λ„ λΆ™μ–΄ μžˆμ§€ μ•ŠμœΌλ―€λ‘œ λ©”μ„œλ“œκ°€ μ’…λ£Œλ˜λ©΄ λ©”λͺ¨λ¦¬μ—μ„œ 였래된 λ…Έλ“œλ₯Ό μ œκ±°ν•©λ‹ˆλ‹€. λ§Œμ•½ λ¦¬μŠ€νŠΈκ°€ λΉ„κ²Œ 되면 tail 을 nil 둜 μ„€μ •ν•©λ‹ˆλ‹€.

ν”Œλ ˆμ΄κ·ΈλΌμš΄λ“œ νŽ˜μ΄μ§€λ‘œ λŒμ•„κ°€μ„œ μ•„λž˜ μ½”λ“œλ₯Ό 밑에 μΆ”κ°€ν•˜μ—¬ ν…ŒμŠ€νŠΈν•©λ‹ˆλ‹€.

example(of: "pop") {
  var list = LinkedList<Int>()
  list.push(3)
  list.push(2)
  list.push(1)

  print("Before popping list: \(list)")
  let poppedValue = list.pop()
  print("After popping list: \(list)")
  print("Popped value: " + String(describing: poppedValue))
}

μ•„λž˜ κ²°κ³Όλ₯Ό μ½˜μ†”μ°½μ—μ„œ λ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€.

---Example of pop---
Before popping list: 1 -> 2 -> 3
After popping list: 2 -> 3
Popped value: Optional(1)

 

removeLast μž‘μ—…

 

리슀트의 λ§ˆμ§€λ§‰ λ…Έλ“œλ₯Ό μ œκ±°ν•˜λŠ” 것은 μ•½κ°„ λΆˆνŽΈν•©λ‹ˆλ‹€. tail λ…Έλ“œμ— λŒ€ν•œ μ°Έμ‘°κ°€ μžˆμ–΄λ„ κ·Έ μ•žμ— μžˆλŠ” λ…Έλ“œμ— λŒ€ν•œ μ°Έμ‘°κ°€ μ—†μœΌλ©΄ μž˜λΌλ‚Ό 수 μ—†μŠ΅λ‹ˆλ‹€. λ•Œλ¬Έμ— μ—¬λŸ¬λΆ„μ€ 수고슀러운 탐색을 ν•΄μ•Όν•©λ‹ˆλ‹€. μ•„λž˜ μ½”λ“œλ₯Ό pop 밑에 μΆ”κ°€ν•©λ‹ˆλ‹€.

 

@discardableResult
public mutating func removeLast() -> Value? {
  // 1
  guard let head = head else {
    return nil
  }
  // 2
  guard head.next != nil else {
    return pop()
  }
  // 3
  var prev = head
  var current = head

  while let next = current.next {
    prev = current
    current = next
  }
  // 4
  prev.next = nil
  tail = prev
  return current.value
}

μ½”λ“œμ—μ„œ μΌμ–΄λ‚˜λŠ” 일은 λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€.

  1. λ§Œμ•½ head κ°€ nil일 경우 아무것도 μ œκ±°λ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. nil 을 λ°˜ν™˜ν•©λ‹ˆλ‹€.
  2. λ§Œμ•½ λ¦¬μŠ€νŠΈκ°€ ν•œ 개의 λ…Έλ“œλ‘œλ§Œ κ΅¬μ„±λ˜μ–΄ μžˆλ‹€λ©΄ removeLast λŠ” κΈ°λŠ₯적으둜 pop κ³Ό λ™μΌν•©λ‹ˆλ‹€. pop 은 head 와 tail 의 레퍼런슀 μ—…λ°μ΄νŠΈλ₯Ό μ²˜λ¦¬ν•˜λ―€λ‘œ, μž‘μ—…μ„ μœ„μž„ν•˜κΈ°λ§Œ ν•˜λ©΄ λ©λ‹ˆλ‹€.
  3. current.next κ°€ nil 일 λ•ŒκΉŒμ§€ 계속 λ‹€μŒ λ…Έλ“œλ₯Ό κ²€μƒ‰ν•©λ‹ˆλ‹€. 즉 current κ°€ 리슀트의 λ§ˆμ§€λ§‰ λ…Έλ“œλ₯Ό μ˜λ―Έν•˜λŠ” μž‘μ—…μž…λ‹ˆλ‹€.
  4. current κ°€ λ§ˆμ§€λ§‰ λ…Έλ“œμ΄λ©΄, prev.next 의 레퍼런슀λ₯Ό μ΄μš©ν•˜μ—¬ λŠμ–΄λ‚΄λ©΄ λ©λ‹ˆλ‹€. tail 레퍼런슀λ₯Ό κΌ­ μ—…λ°μ΄νŠΈ ν•΄μ•Όν•©λ‹ˆλ‹€.

ν”Œλ ˆμ΄κ·ΈλΌμš΄λ“œ νŽ˜μ΄μ§€λ‘œ λŒμ•„κ°€μ„œ λ‹€μŒ μ½”λ“œλ₯Ό μ•„λž˜μ— μΆ”κ°€ν•©λ‹ˆλ‹€.

example(of: "removing the last node") {
  var list = LinkedList<Int>()
  list.push(3)
  list.push(2)
  list.push(1)

  print("Before removing last node: \(list)")
  let removedValue = list.removeLast()

  print("After removing last node: \(list)")
  print("Removed value: " + String(describing: removedValue))
}

μ•„λž˜ μ½˜μ†” μ°½μ—μ„œ μ΄λŸ¬ν•œ 결과물을 λ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€.

---Example of removing the last node---
Before removing last node: 1 -> 2 -> 3
After removing last node: 1 -> 2
Removed value: Optional(3)

removeLast λŠ” 리슀트의 λκΉŒμ§€ μˆœνšŒν•΄μ•Ό ν•©λ‹ˆλ‹€. μ΄λŠ” O(n) μž‘μ—…μœΌλ‘œ μƒλŒ€μ μœΌλ‘œ λΉ„μš©μ΄ 많이 λ“œλŠ” μž‘μ—…μž…λ‹ˆλ‹€.

remove(after:) μž‘μ—…

λ§ˆμ§€λ§‰ 제거 μž‘μ—…μ€ 리슀트의 νŠΉμ • μœ„μΉ˜μ— μžˆλŠ” νŠΉμ • λ…Έλ“œλ₯Ό μ‚­μ œν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€. insert(after:) 와 맀우 μœ μ‚¬ν•©λ‹ˆλ‹€. λ¨Όμ € μ—¬λŸ¬λΆ„μ€ μ œκ±°ν•˜κ³ μž ν•˜λŠ” λ…Έλ“œμ˜ λ°”λ‘œ μ•ž λ…Έλ“œλ₯Ό μ°Ύκ³ , λ‹€μŒμœΌλ‘œλŠ” 연결을 λŠμ„ κ²ƒμž…λ‹ˆλ‹€.

κ°€μš΄λ° λ…Έλ“œλ₯Ό 제거

LinkedList.swift 둜 λŒμ•„κ°€μ„œ removeLast μ•„λž˜μ— λ‹€μŒ λ©”μ„œλ“œλ₯Ό μΆ”κ°€ν•©λ‹ˆλ‹€.

 

@discardableResult
public mutating func remove(after node: Node<Value>) -> Value? {
  defer {
    if node.next === tail {
      tail = node
    }
    node.next = node.next?.next
  }
  return node.next?.value
}

λ…Έλ“œμ˜ 연결을 ν•΄μ œν•˜λ©΄ defer 블둝이 μ‹€ν–‰λ©λ‹ˆλ‹€. λ§Œμ•½ μ‚­μ œλœ λ…Έλ“œκ°€ tail λ…Έλ“œμΌ 경우, tail λ ˆνΌλŸ°μŠ€κ°€ λ°˜λ“œμ‹œ μ—…λ°μ΄νŠΈ λ˜μ–΄μ•Όν•˜λ―€λ‘œ νŠΉλ³„ν•œ μ²˜λ¦¬κ°€ ν•„μš”ν•©λ‹ˆλ‹€.

ν”Œλ ˆμ΄κ·ΈλΌμš΄λ“œλ‘œ λŒμ•„κ°‘μ‹œλ‹€. μ—¬λŸ¬λΆ„μ€ 방법을 μ•Œκ³  μžˆμ–΄μš”.

 

example(of: "removing a node after a particular node") {
  var list = LinkedList<Int>()
  list.push(3)
  list.push(2)
  list.push(1)

  print("Before removing at particular index: \(list)")
  let index = 1
  let node = list.node(at: index - 1)!
  let removedValue = list.remove(after: node)

  print("After removing at index \(index): \(list)")
  print("Removed value: " + String(describing: removedValue))
}

μ½˜μ†” μ°½μ—μ„œ μ•„λž˜ 좜λ ₯을 λ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€.

---Example of removing a node after a particular node---
Before removing at particular index: 1 -> 2 -> 3
After removing at index 1: 1 -> 3
Removed value: Optional(2)

더 λ§Žμ€ μš”μ†Œλ₯Ό μΆ”κ°€ν•˜κ³  인덱슀 값을 가지고 λ†€μ•„λ³΄μ„Έμš”. insert(at:) κ³Ό μœ μ‚¬ν•˜κ²Œ 이 μž‘μ—…μ˜ μ‹œκ°„ λ³΅μž‘λ„λŠ” O(1) μž…λ‹ˆλ‹€. ν•˜μ§€λ§Œ 그전에 νŠΉμ • λ…Έλ“œμ˜ λ ˆνΌλŸ°μŠ€κ°€ μžˆμ–΄μ•Ό ν•©λ‹ˆλ‹€.

 

μ„±λŠ₯ 평가

이제 λ˜λ‹€λ₯Έ μ²΄ν¬ν¬μΈνŠΈμ— λ„μ°©ν–ˆλ„€μš”! μš”μ•½ν•˜μžλ©΄ μ—¬λŸ¬λΆ„μ€ μ—°κ²°λ¦¬μŠ€νŠΈμ—μ„œ 값을 μ‚­μ œν•˜λŠ” 세가지 μž‘μ—…μ„ κ΅¬ν˜„ν•˜μ˜€μŠ΅λ‹ˆλ‹€.

 

  pop removeLast remove(after:)
λ™μž‘ Behaviour headλ₯Ό μ‚­μ œ tail을 μ‚­μ œ λ°”λ‘œ λ‹€μŒ λ…Έλ“œλ₯Ό μ‚­μ œ
μ‹œκ°„λ³΅μž‘λ„ Time complexity O(1) O(n) O(1)

 

이 μ‹œμ μ—μ„œ μ—¬λŸ¬λΆ„μ€ λŒ€λΆ€λΆ„ ν”„λ‘œκ·Έλž˜λ¨Έκ°€ μ—°κ΄€ μžˆμ„ μ—°κ²°λ¦¬μŠ€νŠΈμ˜ μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ •μ˜ν•˜μ˜€μŠ΅λ‹ˆλ‹€. ν•˜μ§€λ§Œ μŠ€μœ„ν”„νŠΈ μ‹œλ§¨ν‹±μ„ κΎΈλ―ΈκΈ°(adorn)μœ„ν•΄μ„œλŠ” 해야될 일이 μžˆμŠ΅λ‹ˆλ‹€. 이번 μ±•ν„°μ˜ λ‚˜λ¨Έμ§€ μ ˆλ°˜μ—μ„œλŠ” μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ°€λŠ₯ν•œ λΉ λ₯΄κ²Œ(Swifty) λ§Œλ“œλŠ” 것에 μ΄ˆμ μ„ λ§žμΆ”κ² μŠ΅λ‹ˆλ‹€.


πŸ”— λ²ˆμ—­ μ‹œλ¦¬μ¦ˆ 링크

0️⃣ μ„Ήμ…˜ 0. μ‹œμž‘ν•˜κΈ°μ „μ—

 

[Swift][λ²ˆμ—­] μŠ€μœ„ν”„νŠΈμ˜ μžλ£Œκ΅¬μ‘°μ™€ μ•Œκ³ λ¦¬μ¦˜ - μ„Ήμ…˜ 0. μ‹œμž‘ν•˜κΈ° 전에

μš”μ¦˜ μ•Œκ³ λ¦¬μ¦˜ 곡뢀λ₯Ό ν•˜λ©΄μ„œ Raywenderlich.com μ—μ„œ λ‚˜μ˜¨ Data Structures & Algorithms in Swift이 책을 보고 μžˆμŠ΅λ‹ˆλ‹€. https://www.raywenderlich.com/books/data-structures-algorithms-in-swift μ €λŠ” μ •..

kimdee.tistory.com

1️⃣ μ„Ήμ…˜ 1. μ†Œκ°œ Introduction

> 챕터 1.μ™œ μžλ£Œκ΅¬μ‘°μ™€ μ•Œκ³ λ¦¬μ¦˜μ„ λ°°μ›Œμ•Όν• κΉŒμš”? / μ±•ν„° 2. λ³΅μž‘λ„  Complexity

 

[Swift][λ²ˆμ—­] μŠ€μœ„ν”„νŠΈμ˜ μžλ£Œκ΅¬μ‘°μ™€ μ•Œκ³ λ¦¬μ¦˜ - μ„Ήμ…˜ 1. μ†Œκ°œ - 챕터1. μ™œ μžλ£Œκ΅¬μ‘°μ™€ μ•Œκ³ λ¦¬μ¦˜μ„

Raywenderlich.com μ—μ„œ λ‚˜μ˜¨ Data Structures & Algorithms in Swift μ±…μ˜ 데λͺ¨ κ³΅κ°œλ³Έμ„ λ²ˆμ—­ν•˜μ˜€μŠ΅λ‹ˆλ‹€. 즐겁게 λ΄μ£Όμ„Έμš”. https://www.raywenderlich.com/books/data-structures-algorithms-in-swift μ„Ήμ…˜..

kimdee.tistory.com

> 챕터3. μŠ€μœ„ν”„νŠΈ ν‘œμ€€ 라이브러리 Swift Standard Library

 

[Swift][λ²ˆμ—­] μŠ€μœ„ν”„νŠΈμ˜ μžλ£Œκ΅¬μ‘°μ™€ μ•Œκ³ λ¦¬μ¦˜ - μ„Ήμ…˜ 1. μ†Œκ°œ - 챕터3. μŠ€μœ„ν”„νŠΈ ν‘œμ€€ 라이브러리 S

Raywenderlich.com μ—μ„œ λ‚˜μ˜¨ Data Structures & Algorithms in Swift μ±…μ˜ 데λͺ¨ κ³΅κ°œλ³Έμ„ λ²ˆμ—­ν•˜μ˜€μŠ΅λ‹ˆλ‹€. 즐겁게 λ΄μ£Όμ„Έμš”. https://www.raywenderlich.com/books/data-structures-algorithms-in-swift μ„Ήμ…˜..

kimdee.tistory.com

 

1️⃣ μ„Ήμ…˜ 2. 기초 자료ꡬ쑰 Elementary Data Structure

> 챕터 4. μŠ€νƒ Stacks /  μ±•ν„° 5. μŠ€νƒ λ„μ „κ³Όμ œ Stack Challenges

 

[Swift][λ²ˆμ—­] μŠ€μœ„ν”„νŠΈμ˜ μžλ£Œκ΅¬μ‘°μ™€ μ•Œκ³ λ¦¬μ¦˜ - μ„Ήμ…˜ 2. 기초 자료ꡬ쑰 - 챕터4~5. μŠ€νƒ, μŠ€νƒ 도전

Raywenderlich.com μ—μ„œ λ‚˜μ˜¨ Data Structures & Algorithms in Swift μ±…μ˜ 데λͺ¨ κ³΅κ°œλ³Έμ„ λ²ˆμ—­ν•˜μ˜€μŠ΅λ‹ˆλ‹€. 즐겁게 λ΄μ£Όμ„Έμš”. https://www.raywenderlich.com/books/data-structures-algorithms-in-swift μ„Ήμ…˜..

kimdee.tistory.com

> 챕터 6-1. μ—°κ²°λ¦¬μŠ€νŠΈ Linked List (μ—°κ²°λ¦¬μŠ€νŠΈ μ •μ˜, μš”μ†Œ μΆ”κ°€, μ‚­μ œ)

 

 

[Swift][λ²ˆμ—­] μŠ€μœ„ν”„νŠΈμ˜ μžλ£Œκ΅¬μ‘°μ™€ μ•Œκ³ λ¦¬μ¦˜ - μ„Ήμ…˜ 2. 기초 자료ꡬ쑰 - 챕터6-1. μ—°κ²°λ¦¬μŠ€νŠΈ (μ •

[Swift][λ²ˆμ—­] μŠ€μœ„ν”„νŠΈμ˜ μžλ£Œκ΅¬μ‘°μ™€ μ•Œκ³ λ¦¬μ¦˜ - μ„Ήμ…˜ 2. 기초 자료ꡬ쑰 - 챕터6-1. μ—°κ²°λ¦¬μŠ€νŠΈ Raywenderlich.com μ—μ„œ λ‚˜μ˜¨ Data Structures & Algorithms in Swift μ±…μ˜ 데λͺ¨ κ³΅κ°œλ³Έμ„ λ²ˆμ—­ν•˜μ˜€μŠ΅λ‹ˆλ‹€. 즐겁..

kimdee.tistory.com

> 챕터 6-2. μ—°κ²°λ¦¬μŠ€νŠΈ Linked List (μŠ€μœ„ν”„νŠΈ ν‘œμ€€ 라이브러리의 μ½œλ ‰μ…˜ ν”„λ‘œν† μ½œ, 카우 Copy-On-Write,  λ°Έλ₯˜ μ‹œλ§¨ν‹±)

 

 

[Swift][λ²ˆμ—­] μŠ€μœ„ν”„νŠΈμ˜ μžλ£Œκ΅¬μ‘°μ™€ μ•Œκ³ λ¦¬μ¦˜ - μ„Ήμ…˜ 2. 기초 자료ꡬ쑰 - 챕터6-2. μ—°κ²°λ¦¬μŠ€νŠΈ

[Swift][λ²ˆμ—­] μŠ€μœ„ν”„νŠΈμ˜ μžλ£Œκ΅¬μ‘°μ™€ μ•Œκ³ λ¦¬μ¦˜ - μ„Ήμ…˜ 2. 기초 자료ꡬ쑰 - 챕터6-2. μ—°κ²°λ¦¬μŠ€νŠΈ (μŠ€μœ„ν”„νŠΈ μ½œλ ‰μ…˜ ν”„λ‘œν† μ½œ, λ°Έλ₯˜ μ‹œλ§¨ν‹±, COW(μΉ΄ν”Ό-온-라이트)) Raywenderlich.com μ—μ„œ λ‚˜μ˜¨ Data Structures &..

kimdee.tistory.com

 

> 챕터 7. μ—°κ²°λ¦¬μŠ€νŠΈ λ„μ „κ³Όμ œ Linked List Challenges

 

[Swift][λ²ˆμ—­] μŠ€μœ„ν”„νŠΈμ˜ μžλ£Œκ΅¬μ‘°μ™€ μ•Œκ³ λ¦¬μ¦˜ - μ„Ήμ…˜ 2. 기초 자료ꡬ쑰 - 챕터7. μ—°κ²°λ¦¬μŠ€νŠΈ 도전

[Swift][λ²ˆμ—­] μŠ€μœ„ν”„νŠΈμ˜ μžλ£Œκ΅¬μ‘°μ™€ μ•Œκ³ λ¦¬μ¦˜ - μ„Ήμ…˜ 2. 기초 자료ꡬ쑰 - 챕터7. μ—°κ²°λ¦¬μŠ€νŠΈ λ„μ „κ³Όμ œ Raywenderlich.com μ—μ„œ λ‚˜μ˜¨ Data Structures & Algorithms in Swift μ±…μ˜ 데λͺ¨ κ³΅κ°œλ³Έμ„ λ²ˆμ—­ν•˜μ˜€μŠ΅λ‹ˆλ‹€..

kimdee.tistory.com

 

 


마치며 

 

μ˜€λŠ˜λ„ μ½μ–΄μ£Όμ…”μ„œ κ°μ‚¬ν•©λ‹ˆλ‹€.

 

κΆκΈˆν•œ 점이 μžˆλ‹€λ©΄ λŒ“κΈ€λ‘œ, 도움이 λ˜μ…¨λ‹€λ©΄ 곡감 λΆ€νƒλ“œλ¦½λ‹ˆλ‹€.

ν˜Ήμ‹œ μˆ˜μ •ν•˜κ±°λ‚˜ ν”Όλ“œλ°±ν•˜μ‹€  λ‚΄μš© μžˆλ‹€λ©΄ μ–Έμ œλ“  λŒ“κΈ€λ‘œ λΆ€νƒλ“œλ¦½λ‹ˆλ‹€.

 

κ°μ‚¬ν•©λ‹ˆλ‹€.

 

 

 

λ°˜μ‘ν˜•