2017-03-01 1 views
2

J'ai écrit arbre rouge-noir dans Kotlin. Fun insertFixup restaure l'équilibre après l'insertion d'un nouvel élément (z: Node? est un nouvel élément). L'algorithme de l'équilibrage des arbres est tiré de here (pages 2-3). Le problème est que Kotlin ne me permet pas de réassignerz-z.parent et z.parent.parent. Je veux z pour être un pointeur. La question est de savoir comment faire comprendre à Kotlin ce que je veux de lui?Paramètre de fonction Kotlin: Val ne peut pas être réaffecté

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: Merci à tous! Toutes les réponses ont été utiles et j'ai trouvé la solution dans vos réponses.

+1

Une note mineure: Je pense que vous pouvez améliorer le code grandement si vous vérifiez si 'Z' est' null' ou non une seule fois au début o f 'insertFixup'. En ce moment, il y a un peu trop de "?" Partout;) – voddan

Répondre

6

paramètres de fonction dans Kotlin sont en lecture seule val « s dans la fonction, donc z ici sera toujours référence à l'objet d'origine qui a été passé.

Si vous avez besoin de modifier ce qu'il souligne alors que votre fonction est en cours d'exécution, vous devrez en faire une copie locale au début de la fonction, puis vous pouvez en faire une var.

Par exemple, vous pouvez commencer votre fonction comme ceci:

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

Cela ne répond pas à la question de savoir comment faire un pointeur "z". – mfulton26

1

paramètres de la fonction Kotlin sont des valeurs en lecture seule et ne sont pas cessibles.

Vous pouvez cependant passer créer un objet ReadWriteProperty à insertFixup pour obtenir/réglage 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) 
    } 
} 

Et si vous êtes prêt à utiliser une propriété au lieu d'une variable, vous pouvez utiliser un property reference pour obtenir/la mise en place newNode de insertFixup:

... 
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 Pourquoi le -1? – mfulton26

+1

Prenez mon +1 pour annuler cela :) –