All Downloads are FREE. Search and download functionalities are using the official Maven repository.

shz.core.st.bst.LWBST Maven / Gradle / Ivy

There is a newer version: 2024.0.2
Show newest version
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 comparator;
    final int[] tree;
    final Offer offer;

    public LWBST(E[] leaf, Comparator 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 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 comparator() {
        return comparator;
    }

    public static  LWBST of(E[] leaf, Comparator comparator, boolean win) {
        return new LWBST<>(leaf, comparator, win);
    }

    public static  LWBST of(E[] leaf, Comparator comparator) {
        return new LWBST<>(leaf, comparator);
    }

    public void sort(Supplier[] sources, Consumer 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());
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy