Merges two consecutive sorted lists in place. - Java java.util

Java examples for java.util:List Sort

Description

Merges two consecutive sorted lists in place.

Demo Code

/**/*  w  ww .java2s . c  om*/
 * Java Modular Image Synthesis Toolkit (JMIST)
 * Copyright (C) 2008-2013 Bradley W. Kimmel
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */
//package com.book2s;
import java.util.Collections;
import java.util.List;

public class Main {
    public static void main(String[] argv) {
        List list = java.util.Arrays.asList("asdf", "book2s.com");
        int split = 42;
        merge(list, split);
    }

    /**
     * Merges two consecutive sorted lists in place.
     * The two sub-lists
     * <code>list.get(0), ..., list.get(split-1)</code> and
     * <code>list.get(split), ..., list.get(list.size() - 1)</code>
     * must be sorted.  The results are undefined otherwise.
     * @param list The <code>List</code> to sort.
     * @param split The number of elements in the first sub-list.
     */
    public static <T extends Comparable<? super T>> void merge(
            List<T> list, int split) {
        int n = list.size();
        if (0 < split && split < n) {
            merge(list, 0, split, n - 1, (int) Math.sqrt(split), 0);
        }
    }

    /**
     * Merges two consecutive sorted lists in place.
     *
     * <p>This implementation is based on:</p>
     *
     * <p>J. Chen, "<a href="http://dx.doi.org/10.1016/j.ipl.2005.11.018">A
     * simple algorithm for in-place merging</a>", Information Processing
     * Letters 98:34-40, 2006.</p>.
     *
     * This algorithm is a direct transcription of Fig. 3 on page 37 of this
     * paper, plus the two modifications indicated in the last paragraph of
     * Sec. 2 (page 38) to increase the efficiency using recursion and to
     * allow the algorithm to "work correctly when y<sub>0</sub> - x<sub>0</sub>
     * &lt; 2k".
     *
     * @param A The <code>List</code> to be merged.
     * @param x0 The index of the start of the first sub-list.
     * @param y0 The index of the start of the second sub-list.
     * @param yn The index of the end of the second sub-list.
     * @param k The block size.
     * @param depth The recursion depth.
     */
    private static <T extends Comparable<? super T>> void merge(List<T> A,
            int x0, int y0, int yn, int k, int depth) {
        int f = (y0 - x0) % k;
        int x = (f == 0) ? (y0 - 2 * k) : (y0 - k - f);
        if (x < x0) {
            x = x0;
        }
        T t = A.get(x);
        A.set(x, A.get(x0));
        int z = x0, y = y0, b1 = x + 1, b2 = y0 - k;
        while ((y - z) > (2 * k)) {
            if (y > yn || A.get(x).compareTo(A.get(y)) <= 0) {
                A.set(z, A.get(x));
                A.set(x, A.get(b1));
                x++;
                if (((x - x0) % k) == f) {
                    if (z < (x - k)) {
                        b2 = x - k;
                    }
                    x = findNextXBlock(A, x0, z, y, k, f, b1, b2);
                }
            } else {
                A.set(z, A.get(y));
                A.set(y, A.get(b1));
                y++;
                if (((y - y0) % k) == 0) {
                    b2 = y - k;
                }
            }
            z++;
            A.set(b1, A.get(z));
            if (z == x) {
                x = b1;
            }
            if (z == b2) {
                b2 = -1;
            }
            b1++;
            if (((b1 - x0) % k) == f) {
                if (b2 == -1) {
                    b1 -= k;
                } else {
                    b1 = b2;
                }
            }
        }
        A.set(z, t);
        if (depth > 0) {
            mergeBandY(A, z, y, yn);
        } else {
            Collections.sort(A.subList(z, y));
            merge(A, z, y, yn, (int) Math.sqrt(k), 1);
        }
    }

    /**
     * Auxiliary method required for merging two consecutive sorted lists in
     * place.
     *
     * <p>This implementation is based on:</p>
     *
     * <p>J. Chen, "<a href="http://dx.doi.org/10.1016/j.ipl.2005.11.018">A
     * simple algorithm for in-place merging</a>", Information Processing
     * Letters 98:34-40, 2006.</p>.
     *
     * This method is a direct transcription of Fig. 4.
     */
    private static <T extends Comparable<? super T>> int findNextXBlock(
            List<T> A, int x0, int z, int y, int k, int f, int b1, int b2) {
        T min1 = null, min2 = null;
        int m = (int) Math.floor(((z - x0 - f) / (double) k)) * k + f + x0;
        if (m <= z) {
            m += k;
        }
        int i = m;
        int j, x = i;
        while ((i + k) <= y) {
            if ((i != b1) && (i != b2)) {
                if ((i < b1) && (b1 < i + k)) {
                    j = m - 1;
                } else {
                    j = i + k - 1;
                }
                if (min1 == null
                        || (A.get(i).compareTo(min1) <= 0 && A.get(j)
                                .compareTo(min2) <= 0)) {
                    x = i;
                    min1 = A.get(i);
                    min2 = A.get(j);
                }
            }
            i += k;
        }
        return x;
    }

    /**
     * Auxiliary method required for merging two consecutive sorted lists in
     * place.
     *
     * <p>This implementation is based on:</p>
     *
     * <p>J. Chen, "<a href="http://dx.doi.org/10.1016/j.ipl.2005.11.018">A
     * simple algorithm for in-place merging</a>", Information Processing
     * Letters 98:34-40, 2006.</p>.
     *
     * This method is a direct transcription of Fig. 5.
     */
    private static <T extends Comparable<? super T>> void mergeBandY(
            List<T> A, int z, int y, int yn) {
        while (z < y && y <= yn) {
            int j = z + indexOfMin(A.subList(z, y));
            if (A.get(j).compareTo(A.get(y)) <= 0) {
                Collections.swap(A, z, j);
            } else {
                Collections.swap(A, z, y);
                y++;
            }
            z++;
        }
        if (z < y) {
            Collections.sort(A.subList(z, yn + 1));
        }
    }

    /**
     * Finds the first index of a minimal element in a list.
     * @param list The <code>List</code> to search.
     * @return The first index of a minimal element in the list.
     */
    public static <T extends Comparable<? super T>> int indexOfMin(
            List<T> list) {
        T min = list.get(0);
        int index = 0;
        for (int i = 0, n = list.size(); i < n; i++) {
            T value = list.get(i);
            if (value.compareTo(min) < 0) {
                min = value;
                index = i;
            }
        }
        return index;
    }
}

Related Tutorials