Code

// 0
func example(str: String, isAction: Bool = true, action: () -> Void) {
    print("---------\(str), isAction: \(isAction)---------")
    
    if isAction {
        action()
    }
}

// 1
public struct ArrayStack<T> {
    fileprivate var elements = [T]()
    public init() {}
    
    // 초기화시 Stack의 내부 요소들의 타입은 <T>
    public init<S : Sequence>(_ s: S) where S.Iterator.Element == T {
        self.elements = Array(s.reversed())
    }
    
    // 마지막 요소를 삭제하고 꺼낸값을 반환
    mutating public func pop() -> T? {
        return self.elements.popLast()
        
    }
    
    mutating public func push(element: T){
        self.elements.append(element)
    }
    
    // 마지막 요소를 삭제하지 않고 반환
    public func peek() -> T? {
        return self.elements.last
    }
    
    public func isEmpty() -> Bool {
        return self.elements.isEmpty
    }
    
    public var count: Int {
        return self.elements.count
    }
}

// 2
/*
 var stack: ArrayStack<String> = ["1","2"...]
 리터럴 문법이 가능
 */
extension ArrayStack: ExpressibleByArrayLiteral {
    public typealias ArrayLiteralElement = T
    public init(arrayLiteral elements: T...) {
        self.elements = elements
    }
}

// 3
/*
 ArrayStack<String>(elements: []) ArrayStack<Int>(elements: [1, 2, 3, 4, 5]) -> [] [1, 2, 3, 4, 5]
 프린트시 요소들만 볼수있음. 혹은, 다른것으로 변경 가능
 */
extension ArrayStack: CustomStringConvertible, CustomDebugStringConvertible {
    
    public var description: String {
        return self.elements.description
    }
    
    public var debugDescription: String {
        return self.elements.debugDescription
    }
}

// 4
extension ArrayStack: Sequence {
    public func makeIterator() -> AnyIterator<T> {
        return AnyIterator(IndexingIterator(_elements: self.elements.lazy.reversed()))
    }
}

// 5
example(str: "Stack") {
    
    var myStack = ArrayStack<Int>()
    
    myStack.push(element: 5)
    myStack.push(element: 44)
    myStack.push(element: 23)
    
    print(myStack)
    
    var x = myStack.pop()
    x = myStack.pop()
    
    x = myStack.pop()
    x = myStack.pop()
    x = myStack.pop()
    
    print(myStack)
    
    myStack.push(element: 87)
    myStack.push(element: 2)
    myStack.push(element: 9)
    
    print(myStack)
    print(type(of: myStack))
    
    for i in myStack {
        print(i)
    }
    print("my stack is: \(myStack)")
}

Stack은 나중에 입력된 것이 먼저 출력되는 LIFO(Last In First Out) 데이터 구조를 나타냅니다. 스택은 배열과 유사하지만, 개별 요소에 접근하기 위한 메소드가 좀더 제한적 입니다. 또한 개별 요소에 대한 무작위 접근을 허용하는 배열과 달리, 스택은 개별 요소에 접근하는 방법을 강하게 제한한 인터페이스를 제공합니다.

전체 코드 주소


Reference

swift-algorithm-club/Stack