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

com.irurueta.sorting.ShellSorter Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (C) 2012 Alberto Irurueta Carro ([email protected])
 *
 * 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.irurueta.sorting;

import java.util.Comparator;

/**
 * Sorts instances of type T in provided arrays using Shell method.
 *
 * @param  Type of instances being sorted.
 *            

* This class is based on algorithm found at * Numerical Recipes. 3rd Edition. Cambridge Press. Chapter 8. p. 422 * Knuth. D.E. 1997, Sorting and Searching, 3rd ed., vol. 3 of The Art of * Computer Programming (Reading, MA: Addison-Wesley) * Sedgewick, R. 1998. Algorithms in C, 3rd ed. (Reading, MA: Addison- * Wesley), Chapter 11. */ @SuppressWarnings("Duplicates") public class ShellSorter extends Sorter { /** * Constant defining increment factor to be used internally. */ private static final int INCREMENT_FACTOR = 3; /** * Constant defining minimum increment before stopping the sorting * process. */ private static final int MIN_INCREMENT = 1; /** * Sorts provided array in ascending order so that {@code * array[i - 1] < array[i]} for any valid i. * This method modifies provided array so that * after execution of this method array elements are ordered. * * @param array Array to be sorted. After execution of this method * elements in array between fromIndex (inclusive) and toIndex * (exclusive) are modified so that they are on ascending order. * @param fromIndex Index were sorting starts (inclusive). * @param toIndex Index were sorting stops (exclusive). * @param comparator Determines whether an element is greater or lower * than another one. * @throws IllegalArgumentException If {@code fromIndex > toIndex}. * @throws ArrayIndexOutOfBoundsException if {@code fromIndex < 0} or * {@code toIndex > array.length}. */ @Override public void sort(final T[] array, final int fromIndex, final int toIndex, final Comparator comparator) { if (fromIndex > toIndex) { throw new IllegalArgumentException(); } if (fromIndex < 0 || toIndex > array.length) { throw new ArrayIndexOutOfBoundsException(); } if (fromIndex == toIndex) { return; } int j; var inc = MIN_INCREMENT; final var n = toIndex - fromIndex; T v; do { inc *= INCREMENT_FACTOR; inc++; } while (inc <= n); // Loop over the partial sorts do { inc /= INCREMENT_FACTOR; // Outer loop of straight insertion for (int i = inc; i < n; i++) { v = array[i + fromIndex]; j = i; // Inner loop of straight insertion while (comparator.compare(array[j - inc + fromIndex], v) > 0) { array[j + fromIndex] = array[j - inc + fromIndex]; j -= inc; if (j < inc) { break; } } array[j + fromIndex] = v; } } while (inc > MIN_INCREMENT); } /** * Sorts provided array in ascending order so that {@code * array[i - 1] < array[i]} for any valid i. * This method modifies provided array so that * after execution of this method array elements are ordered. * An array containing the original indices where elements were * located is returned so that other arrays or collections can be kept * in the same order. * * @param array Array to be sorted. After execution of this method * elements in array between fromIndex (inclusive) and toIndex * (exclusive) are modified so that they are on ascending order. * @param fromIndex Index were sorting starts (inclusive). * @param toIndex Index were sorting stops (exclusive). * @param comparator Determines whether an element is greater or lower * than another one. * @return Array containing original location of elements that have been * sorted. Only elements between fromIndex (inclusive) and toIndex * (exclusive) are modified, the remaining ones are kept in natural * order. * @throws IllegalArgumentException If {@code fromIndex > toIndex}. * @throws ArrayIndexOutOfBoundsException if {@code fromIndex < 0} or * {@code toIndex > array.length}. */ @Override public int[] sortWithIndices(final T[] array, final int fromIndex, final int toIndex, final Comparator comparator) { if (fromIndex > toIndex) { throw new IllegalArgumentException(); } if (fromIndex < 0 || toIndex > array.length) { throw new ArrayIndexOutOfBoundsException(); } final int[] indices = getInitialIndicesVector(array.length); if (fromIndex == toIndex) { return indices; } int j; int b; var inc = MIN_INCREMENT; final var n = toIndex - fromIndex; T v; do { inc *= INCREMENT_FACTOR; inc++; } while (inc <= n); // Loop over the partial sorts do { inc /= INCREMENT_FACTOR; // Outer loop of straight insertion for (int i = inc; i < n; i++) { v = array[i + fromIndex]; b = indices[i + fromIndex]; j = i; // Inner loop of straight insertion while (comparator.compare(array[j - inc + fromIndex], v) > 0) { array[j + fromIndex] = array[j - inc + fromIndex]; indices[j + fromIndex] = indices[j - inc + fromIndex]; j -= inc; if (j < inc) { break; } } array[j + fromIndex] = v; indices[j + fromIndex] = b; } } while (inc > MIN_INCREMENT); return indices; } /** * Returns sorting method of this class. * * @return Sorting method. */ @Override public SortingMethod getMethod() { return SortingMethod.SHELL_SORTING_METHOD; } /** * Sorts provided array in ascending order so that {@code * array[i - 1] < array[i]} for any valid i. * This method modifies provided array so that * after execution of this method array elements are ordered. * * @param array Array to be sorted. After execution of this method * elements in array between fromIndex (inclusive) and toIndex * (exclusive) are modified so that they are on ascending order. * @param fromIndex Index were sorting starts (inclusive). * @param toIndex Index were sorting stops (exclusive). * @throws IllegalArgumentException If {@code fromIndex > toIndex}. * @throws ArrayIndexOutOfBoundsException if {@code fromIndex < 0} or * {@code toIndex > array.length}. */ @Override public void sort(final double[] array, final int fromIndex, final int toIndex) { if (fromIndex > toIndex) { throw new IllegalArgumentException(); } if (fromIndex < 0 || toIndex > array.length) { throw new ArrayIndexOutOfBoundsException(); } if (fromIndex == toIndex) { return; } int j; var inc = MIN_INCREMENT; final var n = toIndex - fromIndex; double v; do { inc *= INCREMENT_FACTOR; inc++; } while (inc <= n); // Loop over the partial sorts do { inc /= INCREMENT_FACTOR; // Outer loop of straight insertion for (int i = inc; i < n; i++) { v = array[i + fromIndex]; j = i; // Inner loop of straight insertion while (array[j - inc + fromIndex] > v) { array[j + fromIndex] = array[j - inc + fromIndex]; j -= inc; if (j < inc) { break; } } array[j + fromIndex] = v; } } while (inc > MIN_INCREMENT); } /** * Sorts provided array in ascending order so that {@code * array[i - 1] < array[i]} for any valid i. * This method modifies provided array so that * after execution of this method array elements are ordered. * An array containing the original indices where elements were * located is returned so that other arrays or collections can be kept * in the same order. * * @param array Array to be sorted. After execution of this method * elements in array between fromIndex (inclusive) and toIndex * (exclusive) are modified so that they are on ascending order. * @param fromIndex Index were sorting starts (inclusive). * @param toIndex Index were sorting stops (exclusive). * @return Array containing original location of elements that have been * sorted. Only elements between fromIndex (inclusive) and toIndex * (exclusive) are modified, the remaining ones are kept in natural * order. * @throws IllegalArgumentException If {@code fromIndex > toIndex}. * @throws ArrayIndexOutOfBoundsException if {@code fromIndex < 0} or * {@code toIndex > array.length}. */ @Override public int[] sortWithIndices(final double[] array, final int fromIndex, final int toIndex) { if (fromIndex > toIndex) { throw new IllegalArgumentException(); } if (fromIndex < 0 || toIndex > array.length) { throw new ArrayIndexOutOfBoundsException(); } final int[] indices = getInitialIndicesVector(array.length); if (fromIndex == toIndex) { return indices; } int j; int b; var inc = MIN_INCREMENT; final var n = toIndex - fromIndex; double v; do { inc *= INCREMENT_FACTOR; inc++; } while (inc <= n); // Loop over the partial sorts do { inc /= INCREMENT_FACTOR; // Outer loop of straight insertion for (int i = inc; i < n; i++) { v = array[i + fromIndex]; b = indices[i + fromIndex]; j = i; // Inner loop of straight insertion while (array[j - inc + fromIndex] > v) { array[j + fromIndex] = array[j - inc + fromIndex]; indices[j + fromIndex] = indices[j - inc + fromIndex]; j -= inc; if (j < inc) { break; } } array[j + fromIndex] = v; indices[j + fromIndex] = b; } } while (inc > MIN_INCREMENT); return indices; } /** * Sorts provided array in ascending order so that {@code * array[i - 1] < array[i]} for any valid i. * This method modifies provided array so that * after execution of this method array elements are ordered. * * @param array Array to be sorted. After execution of this method * elements in array between fromIndex (inclusive) and toIndex * (exclusive) are modified so that they are on ascending order. * @param fromIndex Index were sorting starts (inclusive). * @param toIndex Index were sorting stops (exclusive). * @throws IllegalArgumentException If {@code fromIndex > toIndex}. * @throws ArrayIndexOutOfBoundsException if {@code fromIndex < 0} or * {@code toIndex > array.length}. */ @Override public void sort(final float[] array, final int fromIndex, final int toIndex) { if (fromIndex > toIndex) { throw new IllegalArgumentException(); } if (fromIndex < 0 || toIndex > array.length) { throw new ArrayIndexOutOfBoundsException(); } if (fromIndex == toIndex) { return; } int j; var inc = MIN_INCREMENT; final var n = toIndex - fromIndex; float v; do { inc *= INCREMENT_FACTOR; inc++; } while (inc <= n); // Loop over the partial sorts do { inc /= INCREMENT_FACTOR; // Outer loop of straight insertion for (int i = inc; i < n; i++) { v = array[i + fromIndex]; j = i; // Inner loop of straight insertion while (array[j - inc + fromIndex] > v) { array[j + fromIndex] = array[j - inc + fromIndex]; j -= inc; if (j < inc) { break; } } array[j + fromIndex] = v; } } while (inc > MIN_INCREMENT); } /** * Sorts provided array in ascending order so that {@code * array[i - 1] < array[i]} for any valid i. * This method modifies provided array so that * after execution of this method array elements are ordered. * An array containing the original indices where elements were * located is returned so that other arrays or collections can be kept * in the same order. * * @param array Array to be sorted. After execution of this method * elements in array between fromIndex (inclusive) and toIndex * (exclusive) are modified so that they are on ascending order. * @param fromIndex Index were sorting starts (inclusive). * @param toIndex Index were sorting stops (exclusive). * @return Array containing original location of elements that have been * sorted. Only elements between fromIndex (inclusive) and toIndex * (exclusive) are modified, the remaining ones are kept in natural * order. * @throws IllegalArgumentException If {@code fromIndex > toIndex}. * @throws ArrayIndexOutOfBoundsException if {@code fromIndex < 0} or * {@code toIndex > array.length}. */ @Override public int[] sortWithIndices(final float[] array, final int fromIndex, final int toIndex) { if (fromIndex > toIndex) { throw new IllegalArgumentException(); } if (fromIndex < 0 || toIndex > array.length) { throw new ArrayIndexOutOfBoundsException(); } final var indices = getInitialIndicesVector(array.length); if (fromIndex == toIndex) { return indices; } int j; int b; var inc = MIN_INCREMENT; final var n = toIndex - fromIndex; float v; do { inc *= INCREMENT_FACTOR; inc++; } while (inc <= n); // Loop over the partial sorts do { inc /= INCREMENT_FACTOR; // Outer loop of straight insertion for (int i = inc; i < n; i++) { v = array[i + fromIndex]; b = indices[i + fromIndex]; j = i; // Inner loop of straight insertion while (array[j - inc + fromIndex] > v) { array[j + fromIndex] = array[j - inc + fromIndex]; indices[j + fromIndex] = indices[j - inc + fromIndex]; j -= inc; if (j < inc) { break; } } array[j + fromIndex] = v; indices[j + fromIndex] = b; } } while (inc > MIN_INCREMENT); return indices; } /** * Sorts provided array in ascending order so that {@code * array[i - 1] < array[i]} for any valid i. * This method modifies provided array so that * after execution of this method array elements are ordered. * * @param array Array to be sorted. After execution of this method * elements in array between fromIndex (inclusive) and toIndex * (exclusive) are modified so that they are on ascending order. * @param fromIndex Index were sorting starts (inclusive). * @param toIndex Index were sorting stops (exclusive). * @throws IllegalArgumentException If {@code fromIndex > toIndex}. * @throws ArrayIndexOutOfBoundsException if {@code fromIndex < 0} or * {@code toIndex > array.length}. */ @Override public void sort(final int[] array, final int fromIndex, final int toIndex) { if (fromIndex > toIndex) { throw new IllegalArgumentException(); } if (fromIndex < 0 || toIndex > array.length) { throw new ArrayIndexOutOfBoundsException(); } if (fromIndex == toIndex) { return; } int j; var inc = MIN_INCREMENT; final var n = toIndex - fromIndex; int v; do { inc *= INCREMENT_FACTOR; inc++; } while (inc <= n); // Loop over the partial sorts do { inc /= INCREMENT_FACTOR; // Outer loop of straight insertion for (int i = inc; i < n; i++) { v = array[i + fromIndex]; j = i; // Inner loop of straight insertion while (array[j - inc + fromIndex] > v) { array[j + fromIndex] = array[j - inc + fromIndex]; j -= inc; if (j < inc) { break; } } array[j + fromIndex] = v; } } while (inc > MIN_INCREMENT); } /** * Sorts provided array in ascending order so that {@code * array[i - 1] < array[i]} for any valid i. * This method modifies provided array so that * after execution of this method array elements are ordered. * An array containing the original indices where elements were * located is returned so that other arrays or collections can be kept * in the same order. * * @param array Array to be sorted. After execution of this method * elements in array between fromIndex (inclusive) and toIndex * (exclusive) are modified so that they are on ascending order. * @param fromIndex Index were sorting starts (inclusive). * @param toIndex Index were sorting stops (exclusive). * @return Array containing original location of elements that have been * sorted. Only elements between fromIndex (inclusive) and toIndex * (exclusive) are modified, the remaining ones are kept in natural * order. * @throws IllegalArgumentException If {@code fromIndex > toIndex}. * @throws ArrayIndexOutOfBoundsException if {@code fromIndex < 0} or * {@code toIndex > array.length}. */ @Override public int[] sortWithIndices(final int[] array, final int fromIndex, final int toIndex) { if (fromIndex > toIndex) { throw new IllegalArgumentException(); } if (fromIndex < 0 || toIndex > array.length) { throw new ArrayIndexOutOfBoundsException(); } final int[] indices = getInitialIndicesVector(array.length); if (fromIndex == toIndex) { return indices; } int j; int b; var inc = MIN_INCREMENT; final var n = toIndex - fromIndex; int v; do { inc *= INCREMENT_FACTOR; inc++; } while (inc <= n); // Loop over the partial sorts do { inc /= INCREMENT_FACTOR; // Outer loop of straight insertion for (int i = inc; i < n; i++) { v = array[i + fromIndex]; b = indices[i + fromIndex]; j = i; // Inner loop of straight insertion while (array[j - inc + fromIndex] > v) { array[j + fromIndex] = array[j - inc + fromIndex]; indices[j + fromIndex] = indices[j - inc + fromIndex]; j -= inc; if (j < inc) { break; } } array[j + fromIndex] = v; indices[j + fromIndex] = b; } } while (inc > MIN_INCREMENT); return indices; } /** * Sorts provided array in ascending order so that {@code * array[i - 1] < array[i]} for any valid i. * This method modifies provided array so that * after execution of this method array elements are ordered. * * @param array Array to be sorted. After execution of this method * elements in array between fromIndex (inclusive) and toIndex * (exclusive) are modified so that they are on ascending order. * @param fromIndex Index were sorting starts (inclusive). * @param toIndex Index were sorting stops (exclusive). * @throws IllegalArgumentException If {@code fromIndex > toIndex}. * @throws ArrayIndexOutOfBoundsException if {@code fromIndex < 0} or * {@code toIndex > array.length}. */ @Override public void sort(final long[] array, final int fromIndex, final int toIndex) { if (fromIndex > toIndex) { throw new IllegalArgumentException(); } if (fromIndex < 0 || toIndex > array.length) { throw new ArrayIndexOutOfBoundsException(); } if (fromIndex == toIndex) { return; } int j; var inc = MIN_INCREMENT; final var n = toIndex - fromIndex; long v; do { inc *= INCREMENT_FACTOR; inc++; } while (inc <= n); // Loop over the partial sorts do { inc /= INCREMENT_FACTOR; // Outer loop of straight insertion for (int i = inc; i < n; i++) { v = array[i + fromIndex]; j = i; // Inner loop of straight insertion while (array[j - inc + fromIndex] > v) { array[j + fromIndex] = array[j - inc + fromIndex]; j -= inc; if (j < inc) { break; } } array[j + fromIndex] = v; } } while (inc > MIN_INCREMENT); } /** * Sorts provided array in ascending order so that {@code * array[i - 1] < array[i]} for any valid i. * This method modifies provided array so that * after execution of this method array elements are ordered. * An array containing the original indices where elements were * located is returned so that other arrays or collections can be kept * in the same order. * * @param array Array to be sorted. After execution of this method * elements in array between fromIndex (inclusive) and toIndex * (exclusive) are modified so that they are on ascending order. * @param fromIndex Index were sorting starts (inclusive). * @param toIndex Index were sorting stops (exclusive). * @return Array containing original location of elements that have been * sorted. Only elements between fromIndex (inclusive) and toIndex * (exclusive) are modified, the remaining ones are kept in natural * order. * @throws IllegalArgumentException If {@code fromIndex > toIndex}. * @throws ArrayIndexOutOfBoundsException if {@code fromIndex < 0} or * {@code toIndex > array.length}. */ @Override public int[] sortWithIndices(final long[] array, final int fromIndex, final int toIndex) { if (fromIndex > toIndex) { throw new IllegalArgumentException(); } if (fromIndex < 0 || toIndex > array.length) { throw new ArrayIndexOutOfBoundsException(); } final int[] indices = getInitialIndicesVector(array.length); if (fromIndex == toIndex) { return indices; } int j; int b; var inc = MIN_INCREMENT; final var n = toIndex - fromIndex; long v; do { inc *= INCREMENT_FACTOR; inc++; } while (inc <= n); // Loop over the partial sorts do { inc /= INCREMENT_FACTOR; // Outer loop of straight insertion for (int i = inc; i < n; i++) { v = array[i + fromIndex]; b = indices[i + fromIndex]; j = i; // Inner loop of straight insertion while (array[j - inc + fromIndex] > v) { array[j + fromIndex] = array[j - inc + fromIndex]; indices[j + fromIndex] = indices[j - inc + fromIndex]; j -= inc; if (j < inc) { break; } } array[j + fromIndex] = v; indices[j + fromIndex] = b; } } while (inc > MIN_INCREMENT); return indices; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy