forked from openrs2/openrs2
parent
7a0f94dbde
commit
b25f3c0c58
@ -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…
Reference in new issue