简体   繁体   中英

Merge sort comparisons?

I don't think the number of comparisons using merge sort is correct in my merge sort 2 class/method that returns the number of comparisons. Merge sort 2 is like merge sort but just returns the amount of comparisons. Below is my demo, I have an array of 4 integers {2,55,1,45} and when I run the program it returns 8 comparisons. Can anyone verify if this correct or what I am doing wrong?

My demo:

    ArrayInts[] myInts2 = new ArrayInts[4];

    myInts2[0] = new ArrayInts(2);
    myInts2[1] = new ArrayInts(55);
    myInts2[2] = new ArrayInts(1);
    myInts2[3] = new ArrayInts(45);

    MergeSort.mergeSort(myInts2, 0, 3);

    System.out.println("Sorted using Merge Sort: ");


    for (int index = 0; index < myInts2.length; index++) {
        System.out.println(myInts2[index]);
    }

    System.out.println("Number of comps using Merge Sort: " + MergeSort2.mergeSort2(myInts2, 0, 3));
    System.out.println(" ");

My merge sort 2 class/method:

 public class MergeSort2 {
 private static long comp=0;

public static <T extends Comparable<? super T>> long mergeSort2(T[] data, int min, int max) {
    T[] temp;
    int index1, left, right;


    //return on list of length one

    if (min == max) {
        return comp;
    }

    //find the length and the midpoint of the list

    int size = max - min + 1;
    int pivot = (min + max) / 2;
    temp = (T[]) (new Comparable[size]);

    mergeSort2(data, min, pivot); //sort left half of list
    mergeSort2(data, pivot + 1, max); //sort right half of list

    //copy sorted data into workspace

    for (index1 = 0; index1 < size; index1++) {
        temp[index1] = data[min + index1];
    }

    //merge the two sorted lists

    left = 0;
    right = pivot - min + 1;
    for (index1 = 0; index1 < size; index1++) {
        comp++;
        if (right <= max - min) {

            if (left <= pivot - min) {

                if (temp[left].compareTo(temp[right]) > 0) {

                    data[index1 + min] = temp[right++];
                } else {
                    data[index1 + min] = temp[left++];
                }
            } else {
                data[index1 + min] = temp[right++];
            }
        } else {
            data[index1 + min] = temp[left++];
        }
    }


    return comp;

    }

    }

you are getting 8 because you are incrementing each time the merge loop executes whether there is a comparison or not.

if you change

for (index1 = 0; index1 < size; index1++) {
    comp++;
    if (right <= max - min) {

        if (left <= pivot - min) {

to

for (index1 = 0; index1 < size; index1++) {
    if (right <= max - min) {

        if (left <= pivot - min) {
            comp++;

you will get the number of comparisions made rather than the number of loop iterations.

[0,1,2,3] should yield 4 comparisons
[3,2,1,0] should yield 4 comparisons
[0,2,1,3] should yield 5 comparisons
[0,4,1,5,2,6,3,7] should yield 16 comparisons

merge sort is an O(nlog2n) worst case algorithm.

you also need to change this bit

MergeSort.mergeSort(myInts2, 0, 3);

System.out.println("Sorted using Merge Sort: ");


for (int index = 0; index < myInts2.length; index++) {
    System.out.println(myInts2[index]);
}

System.out.println("Number of comps using Merge Sort: " + MergeSort2.mergeSort2(myInts2, 0, 3));
System.out.println(" ");

to

int result = MergeSort.mergeSort(myInts2, 0, 3);

System.out.println("Sorted using Merge Sort: ");


for (int index = 0; index < myInts2.length; index++) {
    System.out.println(myInts2[index]);
}

System.out.println("Number of comps using Merge Sort: " + result);
System.out.println(" ");

as myInts will be sorted when you output the count so you get the sorted complexity.

to demonstrate the effect of calling sort more than once.

public static void main(String[] args) {
    Integer[] myInts2 = new Integer[4];

    myInts2[0] = new Integer(0);
    myInts2[1] = new Integer(2);
    myInts2[2] = new Integer(1);
    myInts2[3] = new Integer(3);

    System.out.println(new MergeSort2().mergeSort2(myInts2, 0, 3)); // will output 5
    System.out.println(new MergeSort2().mergeSort2(myInts2, 0, 3)); // will output 4
}

Calling the sort a second time will use sorted data not unsorted data so you will get a different result. sorting the array can modify the array so calling the sort multiple times can get different behaviour.

The number of comparisons you are showing is correct for the method you have given us . When an array of length 4 is passed into the method you have given us, the line comp++; is called 8 times. Let me explain.

First, pivot=1 . These lines make two recursive calls:

mergeSort2(data, min, pivot); //sort left half of list
mergeSort2(data, pivot + 1, max); //sort right half of list

After each of these calls complete their two additional nested recursive calls, they go on to increment comp by 2, because the for loop runs a number of iterations equal to size . In both of these calls, size=2 , so after call one, comp=2 , and after call two, comp=4 . Each of these recursive calls in turn make two more recursive calls, however, because in each of these calls, min==max , the method returns on return comp; , never reaching the line to increment comp .

Finally, after the two initial recursive method calls return, the for-loop incrementing comp is called four more times, because in the initial call, size=4 . Thus, comp = 4 + 4 , which equals 8!

If that was confusing, I'll illustrate my answer with the ( min , max ) of each call to mergesort2() .

/* 1. */ (min=0, max=3) -> size=4, comp = comp + 4;
/* 2. */     (min=0, max=1) -> size=2, comp = comp + 2;
/* 3. */         (min=0, max=0) -> size=0, comp = comp + 0;
/* 4. */         (min=1, max=1) -> size=0, comp = comp + 0;
/* 5. */     (min=2, max=3) -> size=2, comp = comp + 2;
/* 6. */         (min=2, max=2) -> size=0, comp = comp + 0;
/* 7. */         (min=3, max=3) -> size=0; comp = comp + 0;

/* TOTAL. */  comp = 0 + 0 + 2 + 0 + 0 + 2 + 4; comp = 8

Hopefully I've made myself clear here!

edit1: BevynQ's answer is correct. My answer focuses more on why your code is returning 8 , while his answer focuses on why your sort method is incorrectly counting comparisons .

edit2: I copied and pasted your code directly into my editor, and made the one-line change BevynQ added. My code works as intended, and I am not seeing the same results you are. Perhaps something else was accidentally changed?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM