shz.core.st.bst.LWBST Maven / Gradle / Ivy
package shz.core.st.bst;
import shz.core.NullHelp;
import java.io.Serializable;
import java.util.Comparator;
import java.util.function.Consumer;
import java.util.function.Supplier;
/**
* 元素为E类型的外部多路排序树(败者树及胜者树)
*/
public final class LWBST implements Serializable {
private static final long serialVersionUID = 616634178588700403L;
@FunctionalInterface
public interface Offer extends Consumer, Serializable {
}
final E[] leaf;
final Comparator super E> comparator;
final int[] tree;
final Offer offer;
public LWBST(E[] leaf, Comparator super E> comparator, boolean win) {
NullHelp.requireNonEmpty(leaf);
NullHelp.requireNonNull(comparator);
this.leaf = leaf;
this.comparator = comparator;
tree = getTree(win);
offer = getOffer(win);
}
public LWBST(E[] leaf, Comparator super E> comparator) {
this(leaf, comparator, true);
}
private int[] getTree(boolean win) {
int[] tree;
if (win) {
tree = new int[(leaf.length << 1)];
for (int i = 0; i < leaf.length; ++i) tree[leaf.length + i] = i;
tree[0] = postVisit1(tree, 1);
} else {
tree = new int[(leaf.length << 1) - 1];
for (int i = 0; i < leaf.length; ++i) tree[leaf.length - 1 + i] = i;
postVisit0(tree, 0);
}
return tree;
}
private int postVisit1(int[] tree, int i) {
int left = i << 1, lwinner = -1, rwinner = -1;
if (left < leaf.length) lwinner = postVisit1(tree, left);
if (left < leaf.length - 1) rwinner = postVisit1(tree, left + 1);
int li = lwinner < 0 ? tree[i << 1] : lwinner;
int ri = rwinner < 0 ? tree[(i << 1) + 1] : rwinner;
if (leaf[li] == null) {
tree[i] = li;
return ri;
}
if (leaf[ri] == null) {
tree[i] = ri;
return li;
}
if (comparator.compare(leaf[li], leaf[ri]) < 0) {
tree[i] = ri;
return li;
}
tree[i] = li;
return ri;
}
private void postVisit0(int[] tree, int i) {
int left = (i << 1) + 1;
if (left < leaf.length - 1) postVisit0(tree, left);
if (left < leaf.length - 2) postVisit0(tree, left + 1);
int li = tree[(i << 1) + 1];
int ri = tree[(i << 1) + 2];
if (leaf[li] != null) tree[i] = leaf[ri] != null && comparator.compare(leaf[li], leaf[ri]) >= 0 ? ri : li;
else if (leaf[ri] != null) tree[i] = ri;
}
private Offer getOffer(boolean win) {
if (win) return e -> {
leaf[tree[0]] = e;
int parent = (tree[0] + leaf.length) >> 1;
int winner = tree[0];
while (parent > 0) {
if (leaf[tree[parent]] != null && (leaf[winner] == null || comparator.compare(leaf[winner], leaf[tree[parent]]) > 0)) {
int loser = tree[parent];
tree[parent] = winner;
winner = loser;
}
parent >>= 1;
}
tree[0] = winner;
};
return e -> {
leaf[tree[0]] = e;
int parent = (tree[0] + leaf.length - 2) >> 1;
while (parent >= 0) {
int li = tree[(parent << 1) + 1];
int ri = tree[(parent << 1) + 2];
if (leaf[li] != null)
tree[parent] = leaf[ri] != null && comparator.compare(leaf[li], leaf[ri]) >= 0 ? ri : li;
else if (leaf[ri] != null) tree[parent] = ri;
parent = (parent - 1) >> 1;
}
};
}
public Comparator super E> comparator() {
return comparator;
}
public static LWBST of(E[] leaf, Comparator super E> comparator, boolean win) {
return new LWBST<>(leaf, comparator, win);
}
public static LWBST of(E[] leaf, Comparator super E> comparator) {
return new LWBST<>(leaf, comparator);
}
public void sort(Supplier extends E>[] sources, Consumer super E> consumer) {
if (sources.length != leaf.length) throw new IllegalArgumentException();
while (leaf[tree[0]] != null) {
consumer.accept(leaf[tree[0]]);
offer.accept(sources[tree[0]].get());
}
}
}