コトリンで赤黒木を書きました。 FuninsertFixupは、新しい要素を挿入した後にバランスを復元します(z:Node?は新しい要素です)。ツリーバランシングのアルゴリズムは、 here (ページ2〜3)から取得されます。 問題は、Kotlinが再割り当てを許可しないことですztoz.parentandz.parent.parent。 zをpointerにする問題は、コトリンに私が彼に何を望んでいるかをどうやって理解させるかです。
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:どうもありがとう!すべての答えは有用であり、私はあなたの返信で解決策を見つけました。
Kotlinの関数パラメーターは関数内では読み取り専用val
であるため、ここでz
は常に渡された元のオブジェクトを参照します。
関数の実行中にポイントするものを変更する必要がある場合は、関数の先頭でローカルコピーを作成する必要があります。その後、var
を作成できます。
たとえば、次のように関数を開始できます。
fun insertFixup(_z: Node?) {
var z = _z
Kotlin関数パラメーターは読み取り専用の値であり、割り当てできません。
ただし、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)
}
}
変数の代わりにプロパティを使用する場合は、代わりにnewNode
から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)
私もこの問題に遭遇しました。私がやったことは、データクラスを作成し、そのデータクラスをパラメーターとして渡し、そのパラメーターを使用してそのプロパティを変更することでした。
data class SomeDataClass(
val x: Int,
val y: Int,
val z: Int
)
fun someMethod(someDataClass: SomeDataClass) {
someDataClass.z = 23 //whatever Int value you please
// more computations...
someDataClass.z = 67 // or whatever new value you need to assign.
}
fun parentMethod() {
val someDataClass = SomeDataClass()
someMethod(someDataClass)
val newZValue = someDataClass.z // someDataClass holds modified data from above
// method
}