Swift中的堆栈实现

时间:2015-07-16 18:52:43

标签: ios swift stack

我是Swift和iOS编程的新手。

我正在尝试测试一个简单的算法并需要一个Stack数组。不必任何花哨的东西(堆栈的Ints会做)。

我从The Swift Programming Language documentation得到了堆栈实现:

struct IntStack {
    var items = [Int]()
    mutating func push(item: Int) {
        items.append(item)
    }
    mutating func pop() -> Int {
        return items.removeLast()
    }
    mutating func count() -> Int {
        return items.count
    }
    mutating func show() {
        println(items)
    }
}

计数和显示功能是我的贡献。但是当我尝试声明一个Stacks数组时,我得到一个错误......

var lines = IntStack()[5]

“IntStack”没有名为subscript的成员

我猜它与Optionals有关,但可以弄清楚它是什么......

任何帮助?

7 个答案:

答案 0 :(得分:8)

详细信息

  • Swift 5.1,Xcode 11.3.1

通用堆栈实现

可堆叠协议

protocol Stackable {
    associatedtype Element
    func peek() -> Element?
    mutating func push(_ element: Element)
    @discardableResult mutating func pop() -> Element?
}

extension Stackable {
    var isEmpty: Bool { peek() == nil }
}

堆栈

struct Stack<Element>: Stackable where Element: Equatable {
    private var storage = [Element]()
    func peek() -> Element? { storage.first }
    mutating func push(_ element: Element) { storage.append(element)  }
    mutating func pop() -> Element? { storage.popLast() }
}

extension Stack: Equatable {
    static func == (lhs: Stack<Element>, rhs: Stack<Element>) -> Bool { lhs.storage == rhs.storage }
}

extension Stack: CustomStringConvertible {
    var description: String { "\(storage)" }
}

extension Stack: ExpressibleByArrayLiteral {
    init(arrayLiteral elements: Self.Element...) { storage = elements }
}

用法

var stack = Stack<Int>()
stack.push(1)
stack.push(2)
stack.push(3)
print(stack.peek())
print(stack.pop())
print(stack)
print(stack == Stack<Int>())
stack = [3,2,1]
print(stack)

答案 1 :(得分:3)

您在那里做的事情没有问题 - 这不是声明数组的语法。如果你想要一个包含5个堆栈的数组,你可以这样做:

[IntStack(), IntStack(), IntStack(), IntStack(), IntStack()]

或者,您可以像这样初始化数组:

Array(count: 5, repeatedValue: IntStack())

此外,您不需要将您的功能标记为mutating,除非它们实际上改变了结构 - 因此count()show()不需要它。< / p>

答案 2 :(得分:2)

可以使用特定于堆栈的方法来扩展数组。这可能是您想要的,也可能不是您想要的,这取决于您是否想禁止像访问这样的数组。

protocol Stack {
    associatedtype Element
    
    mutating func push(item: Element)
    
    // allows discarding the result without generating a warning.
    @discardableResult
    mutating func pop() -> Element?
    
    func peek() -> Element?
    
    var count: Int { get }
}

extension Array: Stack {
    mutating func push(item: Element) {
        self.append(item)
    }
    
    mutating func pop() -> Element? {
        if let last = self.last {
            self.remove(at: self.count - 1)
            return last
        }
        
        return .none
    }
    
    func peek() -> Element? {
        self.last
    }
}

简单的测试用例:

class StackTests: XCTestCase {
    
    func testExample() throws {
        var stack = Array<Int>()
        
        XCTAssertEqual(stack.peek(), .none, "stack is empty, peek returns none")
        XCTAssertEqual(stack.pop(), .none, "stack is empty, pop returns none")

        stack.push(item: 0)
        stack.push(item: 1)
        stack.push(item: 2)
        
        XCTAssertEqual(stack.peek(), 2)
        XCTAssertEqual(stack.pop(), 2)
        
        XCTAssertEqual(stack.peek(), 1)
        XCTAssertEqual(stack.pop(), 1)
        
        XCTAssertEqual(stack.peek(), 0)
        XCTAssertEqual(stack.pop(), 0)
    }
}

答案 3 :(得分:1)

初始化时无需声明堆栈的大小。 Jus称这个就足够了。

var lines = IntStack()

另请注意,count()和show()方法不应该是变异的,因为它们不会以任何方式修改结构。

答案 4 :(得分:0)

这是使用Swift泛型的Stack实现,

struct Fruit {
let fruitName : String
let color : String
init(_ name: String,_ color: String) {
    self.fruitName = name
    self.color = color
}
}

let fruit1 = Fruit("Apple", "Red")
let fruit2 = Fruit("Grapes", "Green")

let fruitStack = Stack<Fruit>()
fruitStack.push(fruit1)
fruitStack.push(fruit2)

let fruitFfromStack = fruitStack.pop()
print("Fruit popped from Stack, Name : \(String(describing: fruitFfromStack?.fruitName)) ,Color : \(String(describing: fruitFfromStack?.color))")
let fruitFfromStack1 = fruitStack.pop()
print("Fruit popped from Stack, Name : \(String(describing: fruitFfromStack1?.fruitName)) ,Color : \(String(describing: fruitFfromStack1?.color))")

完整代码在这里:

https://reactcodes.blogspot.com/2019/01/generic-stack-implementation-with.html

答案 5 :(得分:0)

只需查看此代码。带有通用数据类型且不使用数组的堆栈示例。

class Node<T>: CustomStringConvertible {

let value: T
var next: Node?

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

init(value: T) {
    self.value = value
}
}


// Stack  class to hold all items
class Stack<T>: CustomStringConvertible {

var top: Node<T>?

var description: String {
    guard let top = top else { return "---- Stack is EMPTY ----" }
    return "---- Stack Begin ----\n" + String(describing: top) + "\n---- Stack End ----"
}

// push
func push(_ value: T) {
    let currentTop = top
    top = Node(value: value)
    top?.next = currentTop
}

@discardableResult
func pop() -> T? {
    let currentTop = top
    top = top?.next
    return currentTop?.value
}

@discardableResult
func peek() -> T? {
    return top?.value
}
}

答案 6 :(得分:0)

出色的实施!一个想法:我认为应该是:

{{.PageTitle}}