/* * Copyright (c) 2008-2017, Hazelcast, Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.hazelcast.internal.util.sort; /** <p> * Base class for QuickSort implementations. Works with an abstract notion of a mutable array of * slots addressed by their index. Makes no assumptions on the size or structure of the slots, or on * the way they are compared. * </p><p> * <strong>Not thread-safe</strong> because the contract for implementing subclasses is stateful: * {@link #loadPivot(long)} must update the internal state which is later accessed by * {@link #isGreaterThanPivot(long)} and {@link #isLessThanPivot(long)}. * </p> */ public abstract class QuickSorter { /** * Sort the part of the array that starts at the supplied index and has the supplied length. * * @param startIndex first index of the region to sort * @param length length of the region to sort */ public final void sort(long startIndex, long length) { quickSort(startIndex, length - 1); } /** * Loads the data from the given index as needed to satisfy later calls to {@link #isLessThanPivot(long)} * and {@link #isGreaterThanPivot(long)}. * @param index the index from which to load the data. */ protected abstract void loadPivot(long index); /** * @param index the supplied index. * @return {@code true} if the slot at the supplied index is "less than" the slot remembered by the * previous call to {@link #loadPivot(long)}; {@code false} otherwise. */ protected abstract boolean isLessThanPivot(long index); /** * @param index the supplied index. * @return {@code true} if the slot at the supplied index is "greater than" the slot remembered by the * previous call to {@link #loadPivot(long)}; {@code false} otherwise. */ protected abstract boolean isGreaterThanPivot(long index); /** * Swaps the contents of the slots at the supplied indices. * @param index1 the index from which to swap contents. * @param index2 the other index from which to swap contents. */ protected abstract void swap(long index1, long index2); private void quickSort(long lo, long hi) { if (lo >= hi) { return; } long p = partition(lo, hi); quickSort(lo, p); quickSort(p + 1, hi); } private long partition(long lo, long hi) { loadPivot((lo + hi) >>> 1); long i = lo - 1; long j = hi + 1; while (true) { do { i++; } while (isLessThanPivot(i)); do { j--; } while (isGreaterThanPivot(j)); if (i >= j) { return j; } swap(i, j); } } }