簡體   English   中英

為什么在同時對第二個數組進行排序時,這種合並排序會產生索引越界異常?

[英]Why does this merge sort produce an index out of bounds exception when sorting a second array at the same time?

我一直在研究一種合並排序算法,我最終想用它來對字符串數組進行排序。

理論是我對一個包含我想要排序的 ID 的數組進行排序,其順序與作為字符串的主數組相同,然后對 ID 數組進行排序並對字符串數組執行相同的操作,理論上對它們進行相同的排序方法。

例如,ID 值數組可以是 [1,2,3,4,5],主數組看起來像 ["Name, 1","Name, 2"]...

當我在不包含任何第二個數組部分的情況下運行算法時,它可以正常工作,這是輸出:

[0, 1, 1, 10, 12, 16, 18, 24, 26, 53, 53, 53, 100]

但是當我嘗試添加第二個數組操作時,我得到一個異常說:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 1 out of bounds for length 1
    at s4001175.ct5057.flight.Booker.merge(Booker.java:250)
    at s4001175.ct5057.flight.Booker.mergeSort(Booker.java:236)
    at s4001175.ct5057.flight.Booker.mergeSort(Booker.java:232)
    at s4001175.ct5057.flight.Booker.mergeSort(Booker.java:232)
    at s4001175.ct5057.flight.FlightManagement.passengerStatus(FlightManagement.java:92)
    at s4001175.ct5057.flight.FlightManagement.mainMenu(FlightManagement.java:53)
    at s4001175.ct5057.flight.FlightManagement.main(FlightManagement.java:27)

代碼:

   public void mergeSort(int[] flightIDArr, int arrLength, String[] actualArr) {

//        Flattened array of bookings to 1d array
         String[] flatArray = flattenArray(readBookings());


//         If array does not need to be split as length is already 1
        if (arrLength < 2) {
            return;
        }

        // Middle of the array
        int mid = arrLength / 2;
        //Left array of length of half of the array
        int[] left = new int[mid];
        // Other half of split array, with arrLength-mid size to ensure that it works even if the array is an odd length
        int[] right = new int[arrLength - mid];

        //Mirrored version of previous lines but for string array of what we actually want to sort (booking info)
        String[] actualLeft = new String[mid];
        // Same as above but right side
        String[] actualRight = new String[arrLength - mid];

        // for the elements in left array
        for (int i = 0; i < mid; i++) {
            // filling the left arrays with the info from the full array
            left[i] = flightIDArr[i];
            actualLeft[i] = flatArray[i];

        }
        // for elements in right array
        for (int i = mid; i < arrLength; i++) {
            // filling the right arrays with the info from the full array
            right[i - mid] = flightIDArr[i];
            actualRight[i - mid] = flatArray[i];
        }

        //recursively calls the mergesort algorithm to split the arrays as small as possible
        mergeSort(left, mid, actualLeft);
        mergeSort(right, arrLength - mid, actualRight);

        //re merges the split arrays
        merge(flightIDArr,actualArr, left, right, mid, arrLength - mid, actualLeft,actualRight);
    }

    //Method to merge all the split arrays
    public void merge(
            int[] flightIDArr, String[] actualArr, int[] leftArr, int[] rightArr, int left, int right, String[] actualLeft, String[] actualRight) {

        //setting up variables for looping
        int i = 0, j = 0, k = 0;

        //
        while (i < left && j < right) {
            if (leftArr[i] <= rightArr[j]) {
                flightIDArr[k++] = leftArr[i++];
                actualArr[k++] = actualLeft[i++];
            }
            else {
                flightIDArr[k++] = rightArr[j++];
                actualArr[k++] = actualRight[j++];
            }
        }
        while (i < left) {
            flightIDArr[k++] = leftArr[i++];
            actualArr[k++] = actualLeft[i++];

        }
        while (j < right) {
            flightIDArr[k++] = rightArr[j++];
            actualArr[k++] = actualRight[j++];

        }
//        System.out.println(Arrays.toString(actualArr));
        System.out.println(Arrays.toString(flightIDArr));
    }

我已經嘗試使用 IntelliJ 中的調試器運行程序,並且當從第 250 行開始產生異常時,這些是所涉及的變量的值:

 leftArr: 0:0

actualLeft:

     0:
    "Booking Number: 1 
    Flight Number: 000 
    Passenger Name: Test Name 
    Seat Number: 1 
    Seat Class: First"

所以看起來當代碼中的這個階段到達時,它試圖在這些數組中設置超出其范圍的值,但是在不涉及第二個數組的情況下運行算法時不會發生這種情況,盡管在線上發生了同樣的情況249,在哪里

  flightIDArr[k++] = leftArr[i++];

叫做

編輯新代碼:

使用建議的答案,我更改了我的代碼,這似乎消除了錯誤,但是排序不再正常工作,甚至包括一些數字:

正確的輸出:

 [0, 1, 1, 10, 12, 16, 18, 24, 26, 53, 53, 53, 100]

與新代碼的當前輸出:

[0, 1, 1, 1, 12, 16, 18, 18, 24, 53, 53, 53, 100]

如您所見,原始數據集中現在存在重復值和缺失值。

代碼:

   public void mergeSort(int[] flightIDArr, int arrLength, String[] actualArr) {

//        Flattened array of bookings to 1d array
         String[] flatArray = flattenArray(readBookings());


//         If array does not need to be split as length is already 1
        if (arrLength < 2) {
            return;
        }

        // Middle of the array
        int mid = arrLength / 2;
        //Left array of length of half of the array
        int[] left = new int[mid];
        // Other half of split array, with arrLength-mid size to ensure that it works even if the array is an odd length
        int[] right = new int[arrLength - mid];

        //Mirrored version of previous lines but for string array of what we actually want to sort (booking info)
        String[] actualLeft = new String[mid];
        // Same as above but right side
        String[] actualRight = new String[arrLength - mid];

        // for the elements in left array
        for (int i = 0; i < mid; i++) {
            // filling the left arrays with the info from the full array
            left[i] = flightIDArr[i];
            actualLeft[i] = flatArray[i];

        }
        // for elements in right array
        for (int i = mid; i < arrLength; i++) {
            // filling the right arrays with the info from the full array
            right[i - mid] = flightIDArr[i];
            actualRight[i - mid] = flatArray[i];
        }

        //recursively calls the mergesort algorithm to split the arrays as small as possible
        mergeSort(left, mid, actualLeft);
        mergeSort(right, arrLength - mid, actualRight);

        //re merges the split arrays
        merge(flightIDArr,actualArr, left, right, mid, arrLength - mid, actualLeft,actualRight);
    }

    //Method to merge all the split arrays
    public void merge(
            int[] flightIDArr, String[] actualArr, int[] leftArr, int[] rightArr, int left, int right, String[] actualLeft, String[] actualRight) {

        //setting up variables for looping
        int i = 0, j = 0, k = 0;

        //
        while (i < left && j < right) {
            if (leftArr[i] <= rightArr[j]) {
                flightIDArr[k] = leftArr[i];
                actualArr[k++] = actualLeft[i++];
            }
            else {
                flightIDArr[k] = rightArr[j];
                actualArr[k++] = actualRight[i++];
            }
        }
        while (i < left) {
            flightIDArr[k] = leftArr[i];
            actualArr[k++] = actualLeft[i++];

        }
        while (j < right) {
            flightIDArr[k] = rightArr[j];
            actualArr[k++] = actualRight[j++];

        }
//        System.out.println(Arrays.toString(ActualArr));
        System.out.println(Arrays.toString(flightIDArr));
//        System.out.println(" Actual Array: \n \n  " +(Arrays.toString (actualArr)));
    }

當您使用k++ j++等時,您會增加變量。 您對左右數組都執行此操作。 但你可能只想做一次,而不是兩次。

你想替換這樣的代碼:

if (leftArr[i] <= rightArr[j]) {
    flightIDArr[k++] = leftArr[i++];
    actualArr[k++] = actualLeft[i++];
}

有了這個:

if (leftArr[i] <= rightArr[j]) {
    flightIDArr[k] = leftArr[i];
    actualArr[k++] = actualLeft[i++];
}

或這個:

if (leftArr[i] <= rightArr[j]) {
    flightIDArr[k] = leftArr[i];
    actualArr[k] = actualLeft[i];
    k++; i++;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM