用户输入抛出NegativeArraySizeException;相同的硬编码(均为正)号码有效

时间:2019-03-28 05:42:54

标签: java arrays algorithm java.util.scanner mergesort

我目前正在进行迭代合并排序,该操作要求用户在排序之前生成多少个数字。如果输入大于10的数字,则会出现错误:“线程“ main”中的异常java.lang.NegativeArraySizeException”,但是如果我对相同的确切数字(均为正数)进行硬编码,则程序将按预期工作。为什么会出现此错误,我该如何解决呢?谢谢您的提前帮助。

演示文件:

import java.util.Scanner;

public class MergeSortDemo
{
    public static void main(String[] args)
    {
        Scanner keyboard = new Scanner(System.in);

        //int arraySize = 17;
        int arraySize = MergeSortAlgorithms.getArraySize(keyboard);
        int[] testArray = new int[arraySize];



        MergeSortAlgorithms.fillArray(testArray);
        MergeSortAlgorithms.printArray(testArray);
        MergeSortAlgorithms.mergeSort(testArray);
        MergeSortAlgorithms.printArray(testArray);
    }//ends main
}//ends class

迭代合并排序:

    public static void mergeSort(int arr[])
    {
        int n = arr.length;
        // For current size of subarrays to
        // be merged curr_size varies from
        // 1 to n/2
        int curr_size;

        // For picking starting index of
        // left subarray to be merged
        int left_start;


        // Merge subarrays in bottom up
        // manner. First merge subarrays
        // of size 1 to create sorted
        // subarrays of size 2, then merge
        // subarrays of size 2 to create
        // sorted subarrays of size 4, and
        // so on.
        for (curr_size = 1; curr_size <= n-1;
                    curr_size = 2*curr_size)
        {

            // Pick starting point of different
            // subarrays of current size
            for (left_start = 0; left_start < n-1;
                        left_start += 2*curr_size)
            {
                // Find ending point of left
                // subarray. mid+1 is starting
                // point of right
                int mid = left_start + curr_size - 1;

                int right_end = Math.min(left_start
                            + 2*curr_size - 1, n-1);

                // Merge Subarrays arr[left_start...mid]
                // & arr[mid+1...right_end]
                merge(arr, left_start, mid, right_end);
            }
        }
    }

    public static void merge(int arr[], int l, int m, int r)
    {
        int i, j, k;
        int n1 = m - l + 1;
        int n2 = r - m;

        /* create temp arrays */
        int L[] = new int[n1];
        int R[] = new int[n2];

        /* Copy data to temp arrays L[]
        and R[] */
        for (i = 0; i < n1; i++)
            L[i] = arr[l + i];
        for (j = 0; j < n2; j++)
            R[j] = arr[m + 1+ j];

        /* Merge the temp arrays back into
        arr[l..r]*/
        i = 0;
        j = 0;
        k = l;
        while (i < n1 && j < n2)
        {
            if (L[i] <= R[j])
            {
                arr[k] = L[i];
                i++;
            }
            else
            {
                arr[k] = R[j];
                j++;
            }
            k++;
        }

        /* Copy the remaining elements of
        L[], if there are any */
        while (i < n1)
        {
            arr[k] = L[i];
            i++;
            k++;
        }

        /* Copy the remaining elements of
        R[], if there are any */
        while (j < n2)
        {
            arr[k] = R[j];
            j++;
            k++;
        }
    }

与数组相关的方法:

    public static int getArraySize(Scanner keyboard)
    {
        System.out.printf("How many numbers would you like to generate? \n(More Numbers = Longer Sort): ");
        int returnValue = keyboard.nextInt();

        return returnValue;
    }

    public static void fillArray(int[] array)
    {
        Random random = new Random();

        for(int i = 0; i < array.length; i++)
        {
            int randomNumber = (int)(Math.random() * 700 + 1);
            array[i] = randomNumber;
        }
    }

损坏的输出(数组大小为17):

How many numbers would you like to generate?
(More Numbers = Longer Sort): 17
241 272 539 456 242 571 333 28 292 426 7 595 191 162 1 542 394
Exception in thread "main" java.lang.NegativeArraySizeException
        at MergeSortAlgorithms.merge(MergeSortAlgorithms.java:125)
        at MergeSortAlgorithms.mergeSort(MergeSortAlgorithms.java:112)
        at MergeSortDemo.main(MergeSortDemo.java:17)
Press any key to continue . . .

输出相同,但硬编码数组大小为17:

175 423 562 133 136 53 265 605 312 169 666 630 641 613 176 568 111
53 111 133 136 169 175 176 265 312 423 562 568 605 613 630 641 666
Press any key to continue . . .

编辑: 经过更多测试后,某些较大的数字实际上可以工作。例如,25、30和56可以正常工作。

2 个答案:

答案 0 :(得分:1)

这与从控制台获取输入无关。相反,您的代码中存在错误。

int mid = left_start + curr_size - 1;
int right_end = Math.min(left_start + 2*curr_size - 1, n-1);

请考虑以上内容。每当left_start + 2*curr_size - 1大于n-1时,right_end的值就会变得小于mid

在这种情况下,merge()方法中n2的值将变为负数。因此,错误。纠正此问题后,即可解决问题。

更新 我添加了一些if条件。这是工作代码。

public static void mergeSort(int arr[])
{
    int n = arr.length;
    // For current size of subarrays to
    // be merged curr_size varies from
    // 1 to n/2
    int curr_size;

    // For picking starting index of
    // left subarray to be merged
    int left_start;


    // Merge subarrays in bottom up
    // manner. First merge subarrays
    // of size 1 to create sorted
    // subarrays of size 2, then merge
    // subarrays of size 2 to create
    // sorted subarrays of size 4, and
    // so on.
    for (curr_size = 1; curr_size <= n-1;
                curr_size = 2*curr_size)
    {

        // Pick starting point of different
        // subarrays of current size
        for (left_start = 0; left_start < n-1;
                    left_start += 2*curr_size)
        {
            // Find ending point of left
            // subarray. mid+1 is starting
            // point of right
            int mid = left_start + curr_size - 1;

            int right_end = Math.min(left_start
                        + 2*curr_size - 1, n-1);

            if(right_end<mid)
                right_end=mid;

            // Merge Subarrays arr[left_start...mid]
            // & arr[mid+1...right_end]
            merge(arr, left_start, mid, right_end);
        }
    }
}

public static void merge(int arr[], int l, int m, int r)
{
    int i, j, k;
    int n1 = m - l + 1;
    int n2 = r - m;

    /* create temp arrays */
    int L[] = new int[n1];
    int R[] = new int[n2];

    /* Copy data to temp arrays L[]
    and R[] */
    for (i = 0; i < n1; i++)
        if(l+i<arr.length)
        L[i] = arr[l + i];
    for (j = 0; j < n2; j++)
        if(l+j<arr.length)
        R[j] = arr[m + 1+ j];

    /* Merge the temp arrays back into
    arr[l..r]*/
    i = 0;
    j = 0;
    k = l;
    while (i < n1 && j < n2)
    {
        if (L[i] <= R[j])
        {
            arr[k] = L[i];
            i++;
        }
        else
        {
            arr[k] = R[j];
            j++;
        }
        k++;
    }

    /* Copy the remaining elements of
    L[], if there are any */
    while (i < n1 && i<n1 && k<arr.length)
    {
        arr[k] = L[i];
        i++;
        k++;
    }

    /* Copy the remaining elements of
    R[], if there are any */
    while (j < n2)
    {
        arr[k] = R[j];
        j++;
        k++;
    }
}

不过,我觉得您可以简化代码。

答案 1 :(得分:0)

我尝试运行您的代码。运行得很好。这是控制台上的输出。

How many numbers would you like to generate? 
(More Numbers = Longer Sort): 17

[303, 394, 315, 436, 196, 212, 629, 139, 666, 519, 4, 182, 36, 108, 129, 490, 174]
[4, 36, 108, 129, 139, 174, 182, 196, 212, 303, 315, 394, 436, 490, 519, 629, 666]

没有例外:)