Bibi's DevLog ๐Ÿค“๐ŸŽ

[Swift] Queue ํ ๊ตฌํ˜„ํ•˜๊ธฐ (๋ฐฐ์—ด / ์—ฐ๊ฒฐ๋ฆฌ์ŠคํŠธ / Two Stack / Head ๋ฐฉ์‹) ๋ณธ๋ฌธ

๐Ÿ“ฑ๐ŸŽ iOS/Code Templates

[Swift] Queue ํ ๊ตฌํ˜„ํ•˜๊ธฐ (๋ฐฐ์—ด / ์—ฐ๊ฒฐ๋ฆฌ์ŠคํŠธ / Two Stack / Head ๋ฐฉ์‹)

๋น„๋น„ bibi 2022. 12. 21. 00:50

Queue๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๋‹ค์–‘ํ•œ ๋ฐฉ์‹๋“ค.

Queue ๊ตฌํ˜„ํ•˜๊ธฐ - (1) ๋ฐฐ์—ด

๊ฐ€์žฅ ์‰ฝ์ง€๋งŒ ๊ฐ€์žฅ ์ถ”์ฒœํ•˜์ง€ ์•Š๋Š” ๋ฐฉ๋ฒ•

struct Queue<T>: CustomStringConvertible {

    private var elements: [T] = []
    public init() {}

    var isEmpty: Bool {
        elements.isEmpty
    }

    var peek: T? {
        elements.first
    }

    var description: String {
        if isEmpty { return "Queue is empty..." }
        return "---- Queue start ----\n"
            + elements.map({"\($0)"}).joined(separator: " -> ")
            + "\n---- Queue End ----"
    }

    mutating func enqueue(_ value: T) {
        elements.append(value)
    }

    mutating func dequeue() -> T? {
        isEmpty ? nil : elements.removeFirst()
    }
}

Queue ๊ตฌํ˜„ํ•˜๊ธฐ - (2) ์—ฐ๊ฒฐ๋ฆฌ์ŠคํŠธ(Singly Linked List)

class Node<T>: CustomStringConvertible {

    var value: T
    var next: Node?

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

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


struct Queue<T>: CustomStringConvertible {

    var front: Node<T>?

    var rear: Node<T>?

    init() { }

    var isEmpty: Bool {
        return front == nil
    }

    var description: String {
        guard let front = front else { return "Empty Queue" }
        return String(describing: front)
    }

    var peek: T? {
        return front?.value
    }
}

extension Queue {

    mutating private func push(_ value: T) {
        front = Node(value: value, next: front)
        if rear == nil {
            rear = front
        }
    }

    mutating func enqueue(_ value: T) {
        if isEmpty {
            self.push(value)
            return
        }

        rear?.next = Node(value: value)
        rear = rear?.next
    }

    mutating func dequeue() -> T? {
        defer {
            front = front?.next
            if isEmpty {
                rear = nil
            }
        }
        return front?.value
    }
}

Queue ๊ตฌํ˜„ํ•˜๊ธฐ - (3) Stack ๋‘ ๊ฐœ๋ฅผ ์‚ฌ์šฉํ•ด ๊ตฌํ˜„ (two stacks)

struct TwoStackQueue<T>: CustomStringConvertible {

    private var leftStack: [T] = []
    private var rightStack: [T] = []

    var isEmpty: Bool {
        leftStack.isEmpty && rightStack.isEmpty
    }

    var peek: T? {
        leftStack.isEmpty ? rightStack.first : leftStack.last
    }

    var description: String {

        if isEmpty {
            return "Queue is empty..."
        }
        var allElements: [T] = []
        if leftStack.isEmpty == false {
            allElements.append(contentsOf: leftStack.reversed())
        }
        allElements.append(contentsOf: rightStack)

        return "---- Queue start ----\n"
            + allElements.map({"\($0)"}).joined(separator: " -> ")
            + "\n---- Queue End ----"
    }
}

extension TwoStackQueue {

    mutating func enqueue(_ element: T) {
        rightStack.append(element)
    }
}

extension TwoStackQueue {

    mutating func dequeue() -> T? {

        if isEmpty {
            return nil
        }

        if leftStack.isEmpty {
            leftStack = rightStack.reversed()
            rightStack.removeAll()
        }

        return leftStack.removeLast()
    }
}

Queue ๊ตฌํ˜„ํ•˜๊ธฐ - (4) head๋ฅผ ์‚ฌ์šฉํ•ด ๊ตฌํ˜„

public struct Queue<T> {
      fileprivate var array = [T?]()
      fileprivate var head = 0

      public var isEmpty: Bool {
            return count == 0
      }

      public var count: Int {
            return array.count - head
      }

      public mutating func enqueue(_ element: T) {
            array.append(element)
      }

      public mutating func dequeue() -> T? {
            guard head < array.count, let element = array[head] else { return nil }

            array[head] = nil
            head += 1

            let percentage = Double(head)/Double(array.count)
            if array.count > 50 && percentage > 0.25 {
              array.removeFirst(head)
              head = 0
            }

            return element
      }

      public var front: T? {
            if isEmpty {
              return nil
            } else {
              return array[head]
            }
      }
}