简体   繁体   中英

Output of my merge sort algorithm is not sorted

Below is my code for the merge sort algorithm in java. It takes a string and an int array because I need to sort a string array with the int array. This implementation also counts inversions. My issue is that it's counting inversions fine, but when I print out the arrays themselves, it hasn't been changed at all.

the main method is me testing a 6 long array and printing out the inversions and arrays. when i run this test i get the following printed out.

4
1, 3, 4, 6, 2, 5
1, 3, 4, 6, 2, 5

public class Test {

private static int[] intSorted;
private static String[] stringSorted;

public static void main(String[] args) {

    //Creates new string to sort

    String[] string3 = {"1","3","4","6","2","5"};

    //Creates new int to sort

    int[] intt3 = {1,3,4,6,2,5};

    //Calls sortAndCount on int and prints the number of inversions

    System.out.println(sortAndCount(intt3, string3));

    //Turns the int array into a string to print

    StringBuilder intBuild = new StringBuilder();
    for(int i = 0; i < intSorted.length; i++){
        if(i+1 == intSorted.length){
            intBuild.append(intSorted[i]);
        }
        else{
        intBuild.append(intSorted[i] + ", ");
        }
    }

    //Turns the string array into a string to print

    StringBuilder stringBuild = new StringBuilder();
    for(int i = 0; i < stringSorted.length; i++){
        if(i+1 == stringSorted.length){
            stringBuild.append(stringSorted[i]);
        }
        else{
        stringBuild.append(stringSorted[i] + ", ");
        }
    }

    System.out.println(intBuild);
    System.out.println(stringBuild);


}

private static int sortAndCount(int intToSort[], String stringToSort[]){

    int inversionsLeft;
    int inversionsRight;
    int inversionsMerged;

    if(intToSort.length == 1){
        return 0;
    }

    int m = intToSort.length/2;

    int[] intLeft = new int[m];
    String[] stringLeft = new String[m];

    int[] intRight = new int[intToSort.length-m];
    String[] stringRight = new String[intToSort.length-m];


    for (int i=0; i < m; i++){
        intLeft[i] = intToSort[i];
        stringLeft[i] = stringToSort[i];
    }

    for (int i = 0;i < intRight.length; i++){
            intRight[i] = intToSort[m+i];
            stringRight[i] = stringToSort[m+i];
    }

    inversionsLeft = sortAndCount(intLeft, stringLeft);
    inversionsRight = sortAndCount(intRight, stringRight);

    intSorted = new int[intToSort.length];
    stringSorted = new String[stringToSort.length];

    inversionsMerged = mergeAndCount(intLeft, intRight, stringLeft, stringRight);

    return(inversionsLeft + inversionsRight + inversionsMerged);

}

private static int mergeAndCount(int[] intLeft, int[] intRight, String[] stringLeft, String[] stringRight){

    int count = 0;
    int i = 0;
    int j = 0;
    int k = 0;

    while(i < intLeft.length && j < intRight.length){

        if(intLeft[i] < intRight[j]){
            intSorted[k] = intLeft[i];
            stringSorted[k] = stringLeft[i];
            i++;
        }

        else{
            intSorted[k] = intRight[j];
            stringSorted[k] = stringRight[j];
            count += intLeft.length - i + 1;
            j++;
        }

        k++;

    }

     while (i < intLeft.length)
        {
            intSorted[k] = intLeft[i];
            stringSorted[k] = stringLeft[i];
            k++;
            i++;

        }

     while (j < intRight.length)
        {
            intSorted[k] = intRight[j];
            stringSorted[k] = stringRight[j];
            j++;
            k++;

        }

     return count;

}

I think the problem is here (comments added by me):

    // Create some arrays into which we write the result of merging the 
    // arrays intLeft, intRight, stringLeft, stringRight.
    intSorted = new int[intToSort.length];
    stringSorted = new String[stringToSort.length];

    // Do the merging into intSorted and stringSorted.
    inversionsMerged = mergeAndCount(intLeft, intRight, stringLeft, stringRight);

    // Oops... we haven't updated intToSort and stringToSort!
    // We need to copy the sorted values from intSorted and stringSorted
    // back into intToSort and stringToSort before we return.

    return(inversionsLeft + inversionsRight + inversionsMerged);

I'll leave it up to you to fill in the gap.

I took your code, filled in the gap myself, and ran it. It seemed to work; this was the output I got:

7
1, 2, 3, 4, 5, 6
1, 2, 3, 4, 5, 6

Good luck!

Well the reason that your arrays don't get sorted is that your recursive algorithm keeps recreating the intSorted [] and stringSorted [] with each invocation. Also your recursive method just returns an int (the number of inversions performed). In order of the recursive approach to work each sortAndCount must return it's piece of the array sorted. This makes it difficult to attempt to sort two different arrays in the same algorithm.

I have made a few minor tweaks to your code and now it sorts the int[] correctly.

If you want to count inversions at the same time that you sort, I would suggest adding a passByReference to a Counter object that does nothing but count inversions (like a visitor pattern).

Here is my code:

public class Test {

private static int[] intSorted;

public static void main(String[] args) {

    //Creates new string to sort
    //Creates new int to sort

    int[] intt3 = {1,3,4,6,2,5};

    //Calls sortAndCount on int and prints the number of inversions

    System.out.println(sortAndCount(intt3));

    //Turns the int array into a string to print

    StringBuilder intBuild = new StringBuilder();
    for(int i = 0; i < intSorted.length; i++){
        if(i+1 == intSorted.length){
            intBuild.append(intSorted[i]);
        }
        else{
            intBuild.append(intSorted[i] + ", ");
        }
    }

    //Turns the string array into a string to print


    System.out.println(intBuild);


}

private static int[] sortAndCount(int intToSort[]){

    int inversionsLeft;
    int inversionsRight;
    int inversionsMerged;

    if(intToSort.length == 1){
        return intToSort;
    }

    int m = intToSort.length/2;

    int[] intLeft = new int[m];
    String[] stringLeft = new String[m];

    int[] intRight = new int[intToSort.length-m];
    String[] stringRight = new String[intToSort.length-m];


    for (int i=0; i < m; i++){
        intLeft[i] = intToSort[i];
    }

    for (int i = 0;i < intRight.length; i++){
        intRight[i] = intToSort[m+i];
    }

    intLeft  = sortAndCount(intLeft);
    intRight = sortAndCount(intRight);

    intSorted = new int[intToSort.length];

    intSorted  = mergeAndCount(intLeft, intRight);

    return intSorted;

}

private static int[] mergeAndCount(int[] intLeft, int[] intRight){

    int count = 0;
    int i = 0;
    int j = 0;
    int k = 0;

    while(i < intLeft.length && j < intRight.length){

        if(intLeft[i] < intRight[j]){
            intSorted[k] = intLeft[i];
            i++;
        }

        else{
            intSorted[k] = intRight[j];
            count += intLeft.length - i + 1;
            j++;
        }

        k++;

    }

    while (i < intLeft.length)
    {
        intSorted[k] = intLeft[i];
        k++;
        i++;

    }

    while (j < intRight.length)
    {
        intSorted[k] = intRight[j];
        j++;
        k++;

    }

    return intSorted;

}

}

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