ios Swift中的堆栈实现

h43kikqp  于 2023-01-14  发布在  iOS
关注(0)|答案(7)|浏览(194)

我是Swift和iOS编程的新手。
我试图测试出一个简单的算法,需要一个堆栈数组。不需要任何花哨(堆栈的整数将做)。
我从Swift编程语言文档中获得了Stack实现:

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)
    }
}

count和show函数是我的贡献。但是当我试图声明一个堆栈数组时,我得到了一个错误...

var lines = IntStack()[5]

"IntStack"没有名为subscript的成员
我猜这与可选的东西,但可以找出它是什么。
有人帮忙吗?

ejk8hzay

ejk8hzay1#

详情

  • 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.last }
    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)
bf1o4zei

bf1o4zei2#

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

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

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

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

此外,除非函数实际上改变了结构,否则不需要将函数标记为mutating-因此count()show()不需要。

xwmevbvl

xwmevbvl3#

有可能只使用堆栈特定的方法来扩展数组。这可能是你想要的,也可能不是,这取决于你是否想禁止类似数组的访问。

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)
    }
}
lnxxn5zx

lnxxn5zx4#

初始化时不需要声明堆栈的大小。调用它就足够了。

var lines = IntStack()

还要注意,count()和show()方法不应该改变,因为它们不会以任何方式修改结构体。

atmip9wb

atmip9wb5#

只要看看这个代码。栈例子与泛型数据类型和不使用数组。

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
}
}
qxsslcnc

qxsslcnc6#

出色的执行!一个想法:我想应该是:

func peek() -> Element? { storage.last }
sd2nnvve

sd2nnvve7#

这是一个使用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

相关问题