Convert ForestDisjointSet to Kotlin

pull/48/head
Graham 4 years ago
parent 7a0f94dbde
commit b25f3c0c58
  1. 170
      util/src/main/java/dev/openrs2/util/collect/ForestDisjointSet.java
  2. 117
      util/src/main/java/dev/openrs2/util/collect/ForestDisjointSet.kt

@ -1,170 +0,0 @@
package dev.openrs2.util.collect;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Queue;
public final class ForestDisjointSet<T> implements DisjointSet<T> {
private static final class Node<T> implements Partition<T> {
private final List<Node<T>> children = new ArrayList<>();
private final T value;
private Node<T> parent = this;
private int rank = 0;
private Node(T value) {
this.value = value;
}
private void setParent(Node<T> parent) {
this.parent = parent;
this.parent.children.add(this);
}
private Node<T> find() {
if (parent != this) {
parent = parent.find();
}
return parent;
}
@Override
public Iterator<T> iterator() {
return new NodeIterator<>(find());
}
@SuppressWarnings("unchecked")
@Override
public boolean equals(Object other) {
if (other == null || getClass() != other.getClass()) {
return false;
}
var node = (Node<T>) other;
return find() == node.find();
}
@Override
public int hashCode() {
return find().value.hashCode();
}
@Override
public String toString() {
return find().value.toString();
}
}
private static class NodeIterator<T> implements Iterator<T> {
private final Queue<Node<T>> queue = new ArrayDeque<>();
public NodeIterator(Node<T> root) {
this.queue.add(root);
}
@Override
public boolean hasNext() {
return !queue.isEmpty();
}
@Override
public T next() {
var node = queue.poll();
if (node == null) {
throw new NoSuchElementException();
}
queue.addAll(node.children);
return node.value;
}
}
private static class SetIterator<T> implements Iterator<Partition<T>> {
private final Iterator<Node<T>> it;
public SetIterator(ForestDisjointSet<T> set) {
this.it = new HashSet<>(set.nodes.values()).iterator();
}
@Override
public boolean hasNext() {
return it.hasNext();
}
@Override
public Partition<T> next() {
return it.next();
}
}
private final Map<T, Node<T>> nodes = new HashMap<>();
private int elements = 0, partitions = 0;
@Override
public Partition<T> add(T x) {
var node = nodes.get(x);
if (node != null) {
return node.find();
}
elements++;
partitions++;
nodes.put(x, node = new Node<>(x));
return node;
}
@Override
public Partition<T> get(T x) {
return get0(x);
}
private Node<T> get0(T x) {
var node = nodes.get(x);
if (node == null) {
return null;
}
return node.find();
}
@Override
public void union(Partition<T> x, Partition<T> y) {
var xRoot = ((Node<T>) x).find();
var yRoot = ((Node<T>) y).find();
if (xRoot == yRoot) {
return;
}
if (xRoot.rank < yRoot.rank) {
xRoot.setParent(yRoot);
} else if (xRoot.rank > yRoot.rank) {
yRoot.setParent(xRoot);
} else {
yRoot.setParent(xRoot);
xRoot.rank++;
}
partitions--;
}
@Override
public int getElements() {
return elements;
}
@Override
public int getPartitions() {
return partitions;
}
@Override
public Iterator<Partition<T>> iterator() {
return new SetIterator<>(this);
}
}

@ -0,0 +1,117 @@
package dev.openrs2.util.collect
import java.util.*
import kotlin.NoSuchElementException
class ForestDisjointSet<T> : DisjointSet<T> {
private class Node<T>(val value: T) : DisjointSet.Partition<T> {
val children = mutableListOf<Node<T>>()
private var _parent = this
var parent
get() = _parent
set(parent) {
_parent = parent
_parent.children.add(this)
}
var rank = 0
fun find(): Node<T> {
if (parent !== this) {
_parent = parent.find()
}
return parent
}
override fun iterator(): Iterator<T> {
return NodeIterator(find())
}
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is Node<*>) return false
return find() === other.find()
}
override fun hashCode(): Int {
return find().value.hashCode()
}
override fun toString(): String {
return find().value.toString()
}
}
private class NodeIterator<T>(root: Node<T>) : Iterator<T> {
private val queue = ArrayDeque<Node<T>>()
init {
queue.add(root)
}
override fun hasNext(): Boolean {
return queue.isNotEmpty()
}
override fun next(): T {
val node = queue.poll() ?: throw NoSuchElementException()
queue.addAll(node.children)
return node.value
}
}
private val nodes = mutableMapOf<T, Node<T>>()
override val elements
get() = nodes.size
override var partitions = 0
private set
override fun add(x: T): DisjointSet.Partition<T> {
val node = findNode(x)
if (node != null) {
return node
}
partitions++
val newNode = Node(x)
nodes[x] = newNode
return newNode
}
override fun get(x: T): DisjointSet.Partition<T>? {
return findNode(x)
}
private fun findNode(x: T): Node<T>? {
val node = nodes[x] ?: return null
return node.find()
}
override fun union(x: DisjointSet.Partition<T>, y: DisjointSet.Partition<T>) {
require(x is Node<T>)
require(y is Node<T>)
val xRoot = x.find()
val yRoot = y.find()
if (xRoot == yRoot) {
return
}
if (xRoot.rank < yRoot.rank) {
xRoot.parent = yRoot
} else if (xRoot.rank > yRoot.rank) {
yRoot.parent = xRoot
} else {
yRoot.parent = xRoot
xRoot.rank++
}
partitions--
}
override fun iterator(): Iterator<DisjointSet.Partition<T>> {
return nodes.values.iterator()
}
}
Loading…
Cancel
Save