Пользовательский ввод выдает NegativeArraySizeException; работает тот же номер в жестком коде (ОБА ПОЗИТИВНО) - PullRequest
0 голосов
/ 28 марта 2019

В настоящее время я работаю над итеративной сортировкой слиянием, которая запрашивает у пользователя, сколько чисел нужно сгенерировать перед сортировкой.Если я ввожу число> 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 ]

1 голос
/ 28 марта 2019

Это не имеет никакого отношения к получению ввода с консоли.Вместо этого в вашем коде есть ошибка.

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.

В этом случае значение n2 в методе merge () становится отрицательным.Отсюда и ошибка.Как только вы исправите это, вы решите проблему.

ОБНОВЛЕНИЕ Я добавил несколько 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++;
    }
}

Я чувствую, что вы можете упростить код, хотя.

0 голосов
/ 28 марта 2019

Я пытался запустить твой код.Это бежало отлично.Вот вывод на консоль.

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]

Без исключения:)

...