2017-03-01 3 views
2

Ich habe Rot-schwarz-Baum in Kotlin geschrieben. Fun insertFixup stellt Balance nach dem Einfügen neuer Element (z: Node? ist neues Element). Der Algorithmus des Baumabgleichs wird von here (Seiten 2-3) genommen. Das Problem ist, dass Kotlin erlaubt mir nichtz-z.parent und z.parent.parent neu zuzuweisen. Ich möchte z ein Zeiger sein. Die Frage ist, wie man Kotlin verstehen lässt, was ich von ihm will?Kotlin Funktionsparameter: Val kann nicht neu zugewiesen werden

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: Danke an alle! Alle Antworten waren hilfreich und ich habe die Lösung in Ihren Antworten gefunden.

+1

Ein kleiner Hinweis: ich glaube, Sie stark den Code verbessern können, wenn Sie überprüfen, ob '' Z' null' ist oder nicht nur einmal am Anfang o f 'insertFixup'. Im Moment gibt es ein bisschen zu viel "?" Überall im Ort;) – voddan

Antwort

6

Funktionsparameter in Kotlin sind schreibgeschützt val ‚s innerhalb der Funktion, so z hier immer auf das ursprüngliche Objekt beziehen, die in übergeben wurde.

Wenn Sie ändern müssen, was es Ihre Funktion während Punkte läuft, müssen Sie eine lokale Kopie davon am Anfang der Funktion machen, und dann können Sie eine var machen.

Zum Beispiel könnten Sie Ihre Funktion wie folgt beginnen:

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

Dies beantwortet nicht die Frage, wie man 'Z'-Zeiger-ähnlich macht. – mfulton26

1

Kotlin Funktionsparameter sind schreibgeschützt Werte und sind nicht übertragbar.

Sie können jedoch erstellen ReadWriteProperty Objekt insertFixup passieren/getting newNode Einstellung:

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

Und wenn Sie eine Eigenschaft anstelle einer Variablen bereit zu verwenden sind, dann können Sie eine property reference für verwenden bekommen/Einstellung newNode von insertFixup statt:

... 
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 Warum die -1? – mfulton26

+1

Nimm meine +1, um das rückgängig zu machen :) –

Verwandte Themen