0

So I have a MergeSort algorithm and I want to combine MergeSort with Insertion sort to reduce the overhead of merging, the question is how? I want to sort the segments using insertion sort and then merge.

 public class mergesorttest{
    public static void main(String[]args){
        int d[]= {10,2,3,4,5,6,5,4,3,5,6,7,1};
        mergeSort(d,0,d.length);
        for(int x:d) System.out.print(x+" "); 
        System.out.println(); 
    }

static void mergeSort(int f[],int lb, int ub){
    //termination reached when a segment of size 1 reached -lb+1=ub
    if(lb+1<ub){
        int mid = (lb+ub)/2;
        mergeSort(f,lb,mid);
        mergeSort(f,mid,ub);
        merge(f,lb,mid,ub);
    }
}

static void merge (int f[],int p, int q, int r){
    //p<=q<=r
    int i =p; int j = q; 
    //use temp array to store merged sub-sequence
    int temp[] = new int[r-p]; int t = 0; 
    while(i<q && j<r){
        if(f[i]<=f[j]){
            temp[t] =f[i]; 
            i++;t++;
        }
        else{
            temp[t] = f[j];
            j++;
            t++;
        }

        //tag on remaining sequence
        while(i<q){
            temp[t] = f[i];
            i++;
            t++;

        }
        while(j<r){
            temp[t]=f[j];
            j++;
            t++;
        }
        //copy temp back to f
        i=p;t=0;
        while(t<temp.length){
            f[i]=temp[t];
            i++;
            t++;
        }
        }
}
}

public static void insertion_srt(int array[], int n, int b){
  for (int i = 1; i < n; i++){
  int j = i;
  int B = array[i];
  while ((j > 0) && (array[j-1] > B)){
  array[j] = array[j-1];
  j--;
  }
  array[j] = B;
  }
  }
Bernhard Barker
  • 54,589
  • 14
  • 104
  • 138
Rubee
  • 139
  • 1
  • 2
  • 10

2 Answers2

12

The merging automatically takes care of sorting the elements. However, one can sort using insertion sort when the list gets below some threshold:

static final int THRESHOLD = 10;
static void mergeSort(int f[],int lb, int ub){
    if (ub - lb <= THRESHOLD)
        insertionSort(f, lb, ub);
    else
    {
        int mid = (lb+ub)/2;
        mergeSort(f,lb,mid);
        mergeSort(f,mid,ub);
        merge(f,lb,mid,ub);
    }
}

Doing anything other than this (except playing around with the threshold a little) will increase the time taken by merge sort.

Although merge sort is O(n log n) and insertion sort is O(n2), insertion sort has better constants and is thus faster on very small arrays. This, this, this and this are a few related questions I found.

Community
  • 1
  • 1
Bernhard Barker
  • 54,589
  • 14
  • 104
  • 138
  • This is a good answer, though it helps to go a little bit into the theory of Big O and explain best case/worst case/average case. – Visionary Software Solutions Feb 25 '13 at 08:37
  • 1
    it may be worth mentioning that this is exactly how the built in JDK sort works - for arrays < 7 it does an insertion sort, for > 7 it does a mergesort. – Sean Landsman Feb 25 '13 at 08:58
  • 1
    I thought `Collections.sort()` used quicksort for larger collections. –  Feb 25 '13 at 09:00
  • 1
    @bdares [`Collections.sort`](http://docs.oracle.com/javase/6/docs/api/java/util/Collections.html#sort(java.util.List)) + [`Arrays.sort`](http://docs.oracle.com/javase/6/docs/api/java/util/Arrays.html#sort(java.lang.Object[])) on objects = mergesort. [`Arrays.sort`](http://docs.oracle.com/javase/6/docs/api/java/util/Arrays.html#sort(byte[])) on primitives = quicksort – Bernhard Barker Feb 25 '13 at 09:05
  • Woah that's cool information, guys! Are there links to the relevant source available? – Visionary Software Solutions Feb 25 '13 at 10:11
  • @VisionarySoftwareSolutions I provided links in my previous comment. You can also probably check the Java source. – Bernhard Barker Feb 25 '13 at 11:05
  • I guess what I was asking is if the source for Arrays.sort() and Collections.sort() is available at a non "download the jdk and go into the included files" internet URL for easy lookup, or if the way you came up with this information was by doing exactly that. – Visionary Software Solutions Feb 25 '13 at 11:07
  • 1
    @VisionarySoftwareSolutions I just checked the links I provided, it says which algorithm it uses. But, if you want - [Collections source](http://javasourcecode.org/html/open-source/jdk/jdk-6u23/java/util/Collections.java.html), [Arrays source](http://javasourcecode.org/html/open-source/jdk/jdk-6u23/java/util/Arrays.java.html). Note that if you have the JDK and a proper IDE (NetBeans), opening the source is as easy as Ctrl+Click. – Bernhard Barker Feb 25 '13 at 11:19
  • @Dukeling Why have you taken mid in mergeSort(f,mid,ub) instead of (mid+1)? –  Feb 18 '16 at 19:31
5
public static final int K = 5;

public static void insertionSort(int A[], int p, int q) {
    for (int i = p; i < q; i++) {
        int tempVal = A[i + 1];
        int j = i + 1;
        while (j > p && A[j - 1] > tempVal) {
            A[j] = A[j - 1];
            j--;
        }
        A[j] = tempVal;
    }
    int[] temp = Arrays.copyOfRange(A, p, q +1);
    Arrays.stream(temp).forEach(i -> System.out.print(i + " "));
    System.out.println();
}

public static void merge(int A[], int p, int q, int r) {
    int n1 = q - p + 1;
    int n2 = r - q;
    int[] LA = Arrays.copyOfRange(A, p, q +1);
    int[] RA = Arrays.copyOfRange(A, q+1, r +1);
    int RIDX = 0;
    int LIDX = 0;
    for (int i = p; i < r - p + 1; i++) {
        if (RIDX == n2) {
            A[i] = LA[LIDX];
            LIDX++;
        } else if (LIDX == n1) {
            A[i] = RA[RIDX];
            RIDX++;
        } else if (RA[RIDX] > LA[LIDX]) {
            A[i] = LA[LIDX];
            LIDX++;
        } else {
            A[i] = RA[RIDX];
            RIDX++;
        }
    }
}

public static void sort(int A[], int p, int r) {
    if (r - p > K) {
        int q = (p + r) / 2;
        sort(A, p, q);
        sort(A, q + 1, r);
        merge(A, p, q, r);
    } else {
        insertionSort(A, p, r);
    }
}

public static void main(String string[]) {
    int[] A = { 2, 5, 1, 6, 7, 3, 8, 4, 9 };
    sort(A, 0, A.length - 1);
    Arrays.stream(A).forEach(i -> System.out.print(i + " "));
}
Ankit Anand
  • 63
  • 1
  • 6