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

ciir.umass.edu.utilities.MergeSorter Maven / Gradle / Ivy

The newest version!
/*===============================================================================
 * Copyright (c) 2010-2012 University of Massachusetts.  All Rights Reserved.
 *
 * Use of the RankLib package is subject to the terms of the software license set
 * forth in the LICENSE file included with this software, and also available at
 * http://people.cs.umass.edu/~vdang/ranklib_license.html
 *===============================================================================
 */

package ciir.umass.edu.utilities;

import java.util.Random;
import java.util.logging.Logger;

/**
 *
 * @author vdang
 *
 */
public class MergeSorter {
    private static final Logger logger = Logger.getLogger(MergeSorter.class.getName());

    public static void main(final String[] args) {
        final float[][] f = new float[1000][];
        for (int r = 0; r < f.length; r++) {
            f[r] = new float[500];
            final Random rd = new Random();
            for (int i = 0; i < f[r].length; i++) {
                final float x = rd.nextInt(10);
                f[r][i] = x;
            }
        }
        final double start = System.nanoTime();
        for (final float[] element : f) {
            sort(element, false);
        }
        final double end = System.nanoTime();
        logger.info(() -> "# " + (end - start) / 1e9 + " ");
    }

    public static int[] sort(final float[] list, final boolean asc) {
        return sort(list, 0, list.length - 1, asc);
    }

    public static int[] sort(final float[] list, final int begin, final int end, final boolean asc) {
        final int len = end - begin + 1;
        final int[] idx = new int[len];
        final int[] tmp = new int[len];
        for (int i = begin; i <= end; i++) {
            idx[i - begin] = i;
        }

        //identify natural runs and merge them (first iteration)
        int i = 1;
        int j = 0;
        int k = 0;
        int start = 0;
        final int[] ph = new int[len / 2 + 3];
        ph[0] = 0;
        int p = 1;
        do {
            start = i - 1;
            while (i < idx.length
                    && ((asc && list[begin + i] >= list[begin + i - 1]) || (!asc && list[begin + i] <= list[begin + i - 1]))) {
                i++;
            }
            if (i == idx.length) {
                System.arraycopy(idx, start, tmp, k, i - start);
                k = i;
            } else {
                j = i + 1;
                while (j < idx.length
                        && ((asc && list[begin + j] >= list[begin + j - 1]) || (!asc && list[begin + j] <= list[begin + j - 1]))) {
                    j++;
                }
                merge(list, idx, start, i - 1, i, j - 1, tmp, k, asc);
                i = j + 1;
                k = j;
            }
            ph[p++] = k;
        } while (k < idx.length);
        System.arraycopy(tmp, 0, idx, 0, idx.length);

        //subsequent iterations
        while (p > 2) {
            if (p % 2 == 0) {
                ph[p++] = idx.length;
            }
            k = 0;
            int np = 1;
            for (int w = 0; w < p - 1; w += 2) {
                merge(list, idx, ph[w], ph[w + 1] - 1, ph[w + 1], ph[w + 2] - 1, tmp, k, asc);
                k = ph[w + 2];
                ph[np++] = k;
            }
            p = np;
            System.arraycopy(tmp, 0, idx, 0, idx.length);
        }
        return idx;
    }

    private static void merge(final float[] list, final int[] idx, final int s1, final int e1, final int s2, final int e2, final int[] tmp,
            final int l, final boolean asc) {
        int i = s1;
        int j = s2;
        int k = l;
        while (i <= e1 && j <= e2) {
            if (asc) {
                if (list[idx[i]] <= list[idx[j]]) {
                    tmp[k++] = idx[i++];
                } else {
                    tmp[k++] = idx[j++];
                }
            } else {
                if (list[idx[i]] >= list[idx[j]]) {
                    tmp[k++] = idx[i++];
                } else {
                    tmp[k++] = idx[j++];
                }
            }
        }
        while (i <= e1) {
            tmp[k++] = idx[i++];
        }
        while (j <= e2) {
            tmp[k++] = idx[j++];
        }
    }

    public static int[] sort(final double[] list, final boolean asc) {
        return sort(list, 0, list.length - 1, asc);
    }

    public static int[] sort(final double[] list, final int begin, final int end, final boolean asc) {
        final int len = end - begin + 1;
        final int[] idx = new int[len];
        final int[] tmp = new int[len];
        for (int i = begin; i <= end; i++) {
            idx[i - begin] = i;
        }

        //identify natural runs and merge them (first iteration)
        int i = 1;
        int j = 0;
        int k = 0;
        int start = 0;
        final int[] ph = new int[len / 2 + 3];
        ph[0] = 0;
        int p = 1;
        do {
            start = i - 1;
            while (i < idx.length
                    && ((asc && list[begin + i] >= list[begin + i - 1]) || (!asc && list[begin + i] <= list[begin + i - 1]))) {
                i++;
            }
            if (i == idx.length) {
                System.arraycopy(idx, start, tmp, k, i - start);
                k = i;
            } else {
                j = i + 1;
                while (j < idx.length
                        && ((asc && list[begin + j] >= list[begin + j - 1]) || (!asc && list[begin + j] <= list[begin + j - 1]))) {
                    j++;
                }
                merge(list, idx, start, i - 1, i, j - 1, tmp, k, asc);
                i = j + 1;
                k = j;
            }
            ph[p++] = k;
        } while (k < idx.length);
        System.arraycopy(tmp, 0, idx, 0, idx.length);

        //subsequent iterations
        while (p > 2) {
            if (p % 2 == 0) {
                ph[p++] = idx.length;
            }
            k = 0;
            int np = 1;
            for (int w = 0; w < p - 1; w += 2) {
                merge(list, idx, ph[w], ph[w + 1] - 1, ph[w + 1], ph[w + 2] - 1, tmp, k, asc);
                k = ph[w + 2];
                ph[np++] = k;
            }
            p = np;
            System.arraycopy(tmp, 0, idx, 0, idx.length);
        }
        return idx;
    }

    private static void merge(final double[] list, final int[] idx, final int s1, final int e1, final int s2, final int e2, final int[] tmp,
            final int l, final boolean asc) {
        int i = s1;
        int j = s2;
        int k = l;
        while (i <= e1 && j <= e2) {
            if (asc) {
                if (list[idx[i]] <= list[idx[j]]) {
                    tmp[k++] = idx[i++];
                } else {
                    tmp[k++] = idx[j++];
                }
            } else {
                if (list[idx[i]] >= list[idx[j]]) {
                    tmp[k++] = idx[i++];
                } else {
                    tmp[k++] = idx[j++];
                }
            }
        }
        while (i <= e1) {
            tmp[k++] = idx[i++];
        }
        while (j <= e2) {
            tmp[k++] = idx[j++];
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy