2017-03-01 31 views
2

我已經在Kotlin寫了紅黑樹。樂趣insertFixup插入新元素後恢復平衡(z:節點?是新元素)。樹均衡算法取自here(第2-3頁)。該問題是科特林不允許我重新分配žz.parentz.parent.parent。我想z是一個指針。問題是如何讓Kotlin明白我想從他那裏得到什麼?Kotlin函數參數:Val不能被重新分配

class Node(key: Int) {...} 

class BinarySearchTree { 
    var root: Node? = null 

    fun insert(newNode: Node) {...} 

    fun RotateLeft(x: Node?) {...} 

    fun RotateRight(x: Node?) {...} 

    fun insertFixup(z: Node?) { 
     var y: Node? 
     while (z?.parent?.color == "RED") { 
      if (z?.parent == z?.parent?.parent?.left) { 
       y = z?.parent?.parent?.right 
       if (y?.color == "RED") { 
        z?.parent?.color = "BLACK" 
        y?.color = "BLACK" 
        z?.parent?.parent?.color = "RED" 
        z = z?.parent?.parent 
       } 
       if (z == z?.parent?.right) { 
        z = z?.parent 
        RotateLeft(z) 
        z?.parent?.color = "BLACK" 
        z?.parent?.parent?.color = "RED" 
        RotateRight(z?.parent?.parent) 
       } 
      } else { 
       y = z?.parent?.parent?.left 
       if (y?.color == "RED") { 
        z?.parent?.color = "BLACK" 
        y?.color = "BLACK" 
        z?.parent?.parent?.color = "RED" 
        z = z?.parent?.parent 
       } 
       if (z != z?.parent?.left) { 
        z = z?.parent 
        RotateLeft(z) 
        z?.parent?.color = "BLACK" 
        z?.parent?.parent?.color = "RED" 
        RotateRight(z?.parent?.parent) 
       } 
      } 
     } 
     root?.color = "BLACK" 
    } 
} 

fun main(args: Array<String>) { 
    val bst = BinarySearchTree() 

    while (true) { 
     var newNode = Node(readLine()!!.toInt()) 
     bst.insert(newNode) 
     bst.insertFixup(newNode) 
    } 
} 

UPD:感謝所有!所有的答案都很有幫助,我在你的回覆中找到了解決方案。在科特林

+1

A小調記:我覺得你可以大大提高代碼,如果你檢查是否'z'在開始o是'null'與否只有一次f'insertFixup'。現在到處都是''''' – voddan

回答

6

功能參數爲只讀val的功能裏面,所以z這裏總是引用中傳遞原始對象。

如果您需要修改它指向,而你的功能正在運行,您必須在函數的開頭創建一個本地副本,然後您可以創建一個var

例如,你可以開始你的函數是這樣的:

fun insertFixup(_z: Node?) { 
    var z = _z 
+1

這並不回答關於如何製作'z'指針的問題。 – mfulton26

1

科特林函數的參數是隻讀的值,且不可轉讓。

但是,您可以創建一個ReadWriteProperty對象傳遞給insertFixup來獲得/設置newNode

... 
class BinarySearchTree { 
... 
    fun insertFixup(zProperty: ReadWriteProperty<Any?, Node?>) { 
     var z by zProperty 
... 

fun main(args: Array<String>) { 
    val bst = BinarySearchTree() 

    var newNode: Node? = null 
    val newNodeProperty = object : ReadWriteProperty<Any?, Node?> { 
     override operator fun getValue(thisRef: Any?, property: KProperty<*>): Node? { 
      return newNode 
     } 

     override operator fun setValue(thisRef: Any?, property: KProperty<*>, 
             value: Node?) { 
      newNode = value 
     } 
    } 

    while (true) { 
     newNode = Node(readLine()!!.toInt()) 
     bst.insert(newNode!!) 
     bst.insertFixup(newNodeProperty) 
    } 
} 

如果你願意用一個屬性,而不是一個變量,那麼你可以使用property reference來獲得/從insertFixup設置newNode代替:

... 
class BinarySearchTree { 
... 
    fun insertFixup(zProperty: KMutableProperty0<Node?>) { 
     var z by zProperty 
... 

var newNode: Node? = null 

fun main(args: Array<String>) { 
    val bst = BinarySearchTree() 

    while (true) { 
     newNode = Node(readLine()!!.toInt()) 
     bst.insert(newNode!!) 
     bst.insertFixup(::newNode) 
    } 
} 

// the following allow `KMutableProperty0` to be used as a read/write delegate 
operator fun <T> KProperty0<T>.getValue(thisRef: Any?, property: KProperty<*>): T = get() 
operator fun <T> KMutableProperty0<T>.setValue(thisRef: Any?, property: KProperty<*>, 
               value: T) = set(value) 
+1

@WhoeverMarkedMyAnswerAsNotUseful爲什麼-1? – mfulton26

+1

以我的+1來撤消那:) –