mirror of
https://github.com/TheAlgorithms/Java.git
synced 2025-07-08 18:32:56 +08:00
Improving BitonicSort (#5244)
* Improving BitonicSort * Moving max method to SortingUtils * Adding Javadoc to merge method * Fix for test and code improvements * Improving code readability * Renaming method parameters --------- Co-authored-by: alx <alx@alx.com> Co-authored-by: vil02 <65706193+vil02@users.noreply.github.com>
This commit is contained in:
@ -1,79 +1,112 @@
|
|||||||
package com.thealgorithms.sorts;
|
package com.thealgorithms.sorts;
|
||||||
|
|
||||||
/* Java program for Bitonic Sort. Note that this program
|
import java.util.Arrays;
|
||||||
works only when size of input is a power of 2. */
|
import java.util.function.BiPredicate;
|
||||||
public class BitonicSort {
|
|
||||||
|
|
||||||
/* The parameter dir indicates the sorting direction,
|
/**
|
||||||
ASCENDING or DESCENDING; if (a[i] > a[j]) agrees
|
* BitonicSort class implements the SortAlgorithm interface using the bitonic sort technique.
|
||||||
with the direction, then a[i] and a[j] are
|
*/
|
||||||
interchanged. */
|
public class BitonicSort implements SortAlgorithm {
|
||||||
void compAndSwap(int[] a, int i, int j, int dir) {
|
private enum Direction {
|
||||||
if ((a[i] > a[j] && dir == 1) || (a[i] < a[j] && dir == 0)) {
|
DESCENDING,
|
||||||
// Swapping elements
|
ASCENDING,
|
||||||
int temp = a[i];
|
|
||||||
a[i] = a[j];
|
|
||||||
a[j] = temp;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* It recursively sorts a bitonic sequence in ascending
|
/**
|
||||||
order, if dir = 1, and in descending order otherwise
|
* Sorts the given array using the Bitonic Sort algorithm.
|
||||||
(means dir=0). The sequence to be sorted starts at
|
*
|
||||||
index position low, the parameter cnt is the number
|
* @param <T> the type of elements in the array, which must implement the Comparable interface
|
||||||
of elements to be sorted.*/
|
* @param array the array to be sorted
|
||||||
void bitonicMerge(int[] a, int low, int cnt, int dir) {
|
* @return the sorted array
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public <T extends Comparable<T>> T[] sort(T[] array) {
|
||||||
|
if (array.length == 0) {
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
final int paddedSize = nextPowerOfTwo(array.length);
|
||||||
|
T[] paddedArray = Arrays.copyOf(array, paddedSize);
|
||||||
|
|
||||||
|
// Fill the padded part with a maximum value
|
||||||
|
final T maxValue = max(array);
|
||||||
|
Arrays.fill(paddedArray, array.length, paddedSize, maxValue);
|
||||||
|
|
||||||
|
bitonicSort(paddedArray, 0, paddedSize, Direction.ASCENDING);
|
||||||
|
return Arrays.copyOf(paddedArray, array.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T extends Comparable<T>> void bitonicSort(final T[] array, final int low, final int cnt, final Direction direction) {
|
||||||
if (cnt > 1) {
|
if (cnt > 1) {
|
||||||
int k = cnt / 2;
|
final int k = cnt / 2;
|
||||||
|
|
||||||
|
// Sort first half in ascending order
|
||||||
|
bitonicSort(array, low, k, Direction.ASCENDING);
|
||||||
|
|
||||||
|
// Sort second half in descending order
|
||||||
|
bitonicSort(array, low + k, cnt - k, Direction.DESCENDING);
|
||||||
|
|
||||||
|
// Merge the whole sequence in ascending order
|
||||||
|
bitonicMerge(array, low, cnt, direction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Merges the bitonic sequence in the specified direction.
|
||||||
|
*
|
||||||
|
* @param <T> the type of elements in the array, which must be Comparable
|
||||||
|
* @param array the array containing the bitonic sequence to be merged
|
||||||
|
* @param low the starting index of the sequence to be merged
|
||||||
|
* @param cnt the number of elements in the sequence to be merged
|
||||||
|
* @param direction the direction of sorting
|
||||||
|
*/
|
||||||
|
private <T extends Comparable<T>> void bitonicMerge(T[] array, int low, int cnt, Direction direction) {
|
||||||
|
if (cnt > 1) {
|
||||||
|
final int k = cnt / 2;
|
||||||
|
|
||||||
|
final BiPredicate<T, T> areSorted = (direction == Direction.ASCENDING) ? (a, b) -> a.compareTo(b) < 0 : (a, b) -> a.compareTo(b) > 0;
|
||||||
for (int i = low; i < low + k; i++) {
|
for (int i = low; i < low + k; i++) {
|
||||||
compAndSwap(a, i, i + k, dir);
|
if (!areSorted.test(array[i], array[i + k])) {
|
||||||
}
|
SortUtils.swap(array, i, i + k);
|
||||||
bitonicMerge(a, low, k, dir);
|
|
||||||
bitonicMerge(a, low + k, k, dir);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This funcion first produces a bitonic sequence by
|
bitonicMerge(array, low, k, direction);
|
||||||
recursively sorting its two halves in opposite sorting
|
bitonicMerge(array, low + k, cnt - k, direction);
|
||||||
orders, and then calls bitonicMerge to make them in
|
|
||||||
the same order */
|
|
||||||
void bitonicSort(int[] a, int low, int cnt, int dir) {
|
|
||||||
if (cnt > 1) {
|
|
||||||
int k = cnt / 2;
|
|
||||||
|
|
||||||
// sort in ascending order since dir here is 1
|
|
||||||
bitonicSort(a, low, k, 1);
|
|
||||||
|
|
||||||
// sort in descending order since dir here is 0
|
|
||||||
bitonicSort(a, low + k, k, 0);
|
|
||||||
|
|
||||||
// Will merge whole sequence in ascending order
|
|
||||||
// since dir=1.
|
|
||||||
bitonicMerge(a, low, cnt, dir);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*Caller of bitonicSort for sorting the entire array
|
/**
|
||||||
of length N in ASCENDING order */
|
* Finds the next power of two greater than or equal to the given number.
|
||||||
void sort(int[] a, int n, int up) {
|
*
|
||||||
bitonicSort(a, 0, n, up);
|
* @param n the number
|
||||||
|
* @return the next power of two
|
||||||
|
*/
|
||||||
|
private static int nextPowerOfTwo(int n) {
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
// First n in the below condition is for the case where n is 0
|
||||||
|
if ((n & (n - 1)) == 0) {
|
||||||
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* A utility function to print array of size n */
|
while (n != 0) {
|
||||||
static void printArray(int[] arr) {
|
n >>= 1;
|
||||||
int n = arr.length;
|
count += 1;
|
||||||
for (int i = 0; i < n; ++i) {
|
|
||||||
System.out.print(arr[i] + " ");
|
|
||||||
}
|
|
||||||
System.out.println();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) {
|
return 1 << count;
|
||||||
int[] a = {3, 7, 4, 8, 6, 2, 1, 5};
|
}
|
||||||
int up = 1;
|
|
||||||
BitonicSort ob = new BitonicSort();
|
/**
|
||||||
ob.sort(a, a.length, up);
|
* Finds the maximum element in the given array.
|
||||||
System.out.println("\nSorted array");
|
*
|
||||||
printArray(a);
|
* @param <T> the type of elements in the array, which must implement the Comparable interface
|
||||||
|
* @param array the array to be searched
|
||||||
|
* @return the maximum element in the array
|
||||||
|
* @throws IllegalArgumentException if the array is null or empty
|
||||||
|
*/
|
||||||
|
private static <T extends Comparable<T>> T max(final T[] array) {
|
||||||
|
return Arrays.stream(array).max(Comparable::compareTo).orElseThrow();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,8 @@
|
|||||||
|
package com.thealgorithms.sorts;
|
||||||
|
|
||||||
|
public class BitonicSortTest extends SortingAlgorithmTest {
|
||||||
|
@Override
|
||||||
|
SortAlgorithm getSortAlgorithm() {
|
||||||
|
return new BitonicSort();
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user