具有选项,泛型和可比较的函数确实满足编译器要求

时间:2017-02-16 14:35:05

标签: swift generics

我正在阅读一些算法并且正在使用二叉搜索树。我做了以下

class TreeNode<T: Comparable>{
    var value: T
    var parent: TreeNode?
    var leftChild: TreeNode?
    var rightChild: TreeNode?

    init(value: T) {
        self.value = value
    }
    // ... more stuff ...

哪个工作正常。我有搜索,插入和打印并运行,但是当我试图实现isSame时,如果两个树是相同的,编译器将不接受我的任何函数声明:

首先我尝试:

func isSame(leftNode: TreeNode?, rightNode: TreeNode?) -> Bool {

编译器告诉我&#34;参考泛型类型&#39; TreeNode&#39;需要参数&#34;

并建议添加,然后我做,但现在编译器要我插入&#39;,&#39;在最后一个参数

之后
func isSame(leftNode: TreeNode?, rightNode: TreeNode<T: Comparable>?) -> Bool {

如果我这样做,建议我添加另一个:D

导致类似

的内容
func isSame(leftNode: TreeNode?, rightNode: TreeNode<T: Comparable>?,,,) -> Bool {

编译器,我已遵守你的每一个命令。你还想要我什么?

我可以通过剥离通用部分的功能来解决这个问题:

func isSame(leftNode: TreeNode<Int>?, rightNode: TreeNode<Int>?) -> Bool {

但我很好奇我必须做些什么来使函数与泛型类型一起工作?

TLDR:如何让isSame函数接受这两个通用参数?

完整代码:

import UIKit

class TreeNode<T: Comparable>{
    var value: T
    var parent: TreeNode?
    var leftChild: TreeNode?
    var rightChild: TreeNode?

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

    convenience init(array: [T]){
        precondition(array.count > 0) // test denne

        self.init(value: array.first!)

        for item in array.dropFirst(){
            self.insert(item)
        }
    }

    func insert(_ newValue: T){
        if newValue < self.value {

            if leftChild == nil {
                leftChild = TreeNode(value: newValue)
                leftChild?.parent = self
            } else {
                leftChild!.insert(newValue)
            }
        }
        else {

            if rightChild == nil {
                rightChild = TreeNode(value: newValue)
                rightChild?.parent = self
            } else {
                rightChild!.insert(newValue)
            }
        }
    }

    func search(_ targetValue: T) -> Bool{

        if targetValue < self.value{
            if let leftChild = leftChild{
                return leftChild.search(targetValue)
            }
        }
        if targetValue > self.value{
            if let rightChild = rightChild{
                return rightChild.search(targetValue)
            }
        }
        if targetValue == value{
            print("found \(targetValue)")
            return true
        }
        print("did not find \(targetValue)")
        return false
    }
}

// MARK: - Extensions

extension TreeNode: CustomStringConvertible{
    var description: String {

        var s = ""

        if let left = self.leftChild {
            s += "(\(left.description)) <-"
        }
        s += " \(value) "

        if let right = self.rightChild {
            s += "-> (\(right.description))"
        }
        return s
    }
}

// isSame

func isSame(leftNode: TreeNode<Int>?, rightNode: TreeNode<Int>?) -> Bool {

        if ((leftNode != nil && rightNode == nil) || (rightNode == nil && leftNode != nil)){
            print("xor check returned false")
            return false
        }

        if leftNode?.value != rightNode?.value {
            return false
        }

        if isSame(leftNode: leftNode?.leftChild, rightNode: rightNode?.leftChild){
            return isSame(leftNode: leftNode?.rightChild, rightNode: rightNode?.rightChild)
        } else {
            return false
        }
}


// MARK: - Testing

var smallTree: TreeNode<Int> = TreeNode(value: 13)
var rootNodeFromArray = TreeNode(array: [7, 2, 5, 10, 9, 1])

// isSame test

let treeA: TreeNode<Int> = TreeNode(array: [7, 2, 5, 10, 9, 1])
let treeB: TreeNode<Int> = TreeNode(array: [7, 2, 5, 10, 9, 1])

2 个答案:

答案 0 :(得分:2)

如果函数是全局函数,则可以使其成为通用函数:

func isSame<T>(leftNode: TreeNode<T>?, rightNode: TreeNode<T>?) -> Bool {

这正是Equatable协议的实现方式:

func == <T: Equatable>(lhs: TreeNode<T>, rhs: TreeNode<T>) -> Bool {
    return lhs.value == rhs.value
       && lhs.leftChild == rhs.leftChild
       && lhs.rightChild == rhs.rightChild
}

请注意,Equatable协议不需要可选参数。与nil的比较将自动处理。

然后您只需使用leftNode == rightNode进行比较。

答案 1 :(得分:1)

您可以将isSame函数放在类中:

class TreeNode<T: Comparable> {

    // code here

    class func isSame(leftNode: TreeNode<T>?, rightNode: TreeNode<T>?) -> Bool {
        // code here
        return true
    }
}