有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java我的合并排序对于数组长度10不起作用,有什么原因吗

我正在设置合并排序以对数组进行排序。目标是对任意长度的数组进行排序

我试过查看mergesort函数,但没有发现任何问题。排序适用于某些数组长度(无论是奇数还是偶数),但对于数组长度(如长度10),我得到了一个超限异常

import java.util.Arrays;

class MergeSort
{
 // Merge two sorted sub-arrays A[from .. mid] and A[mid + 1 .. to]
 public static void merge(int[] A, int[] temp, int from, int mid, int to)
 {
  int k = from, i = from, j = mid + 1;

  // loop till there are elements in the left and right runs
  while (i <= mid && j <= to) {
   if (A[i] < A[j]) {
    temp[k++] = A[i++];
   } else {
    temp[k++] = A[j++];
   }
  }

  // Copy remaining elements
  while (i <= mid) {
   temp[k++] = A[i++];
  }

  // Don't need to copy second half

  // copy back to the original array to reflect sorted order
  for (i = from; i <= to; i++) {
   A[i] = temp[i];
  }
 }

 // Iteratively sort array A[low..high] using temporary array
 public static void mergesort(int[] A)
 {
  int low = 0;
  int high = A.length - 1;

  // sort array A[] using temporary array temp
  int[] temp = Arrays.copyOf(A, A.length);

  // divide the array into blocks of size m
  // m = [1, 2, 4, 8, 16...]
  for (int m = 1; m <= high - low; m = 2*m)
  {
   // for m = 1, i = 0, 2, 4, 6, 8...
   // for m = 2, i = 0, 4, 8, 12...
   // for m = 4, i = 0, 8, 16...
   // ...
   for (int i = low; i < high; i += 2*m)
   {
    int from = i;
    int mid = i + m - 1;
    int to = Integer.min(i + 2 * m - 1, high);

    merge(A, temp, from, mid, to);
   }
  }
 }

 // Iterative Implementation of Mergesort algorithm
 public static void main(String[] args)
 {
  int[] A = { 5, 7, -9, 3, -4, 2, 8, 8, 10, 11 };

  System.out.println("Original Array : " + Arrays.toString(A));
  mergesort(A);
  System.out.println("Modified Array : " + Arrays.toString(A));
 }
}

共 (2) 个答案

  1. # 1 楼答案

    以下是您的解决方案:

    为mid添加了一个if语句,使其不跨越数组边界

    if(mid<high) {
                merge(A, temp, from, mid, to);
            }
    

    完整代码:

    // Merge two sorted sub-arrays A[from .. mid] and A[mid + 1 .. to]
    public static void merge(int[] A, int[] temp, int from, int mid, int to)
    {
        int k = from, i = from, j = mid + 1;
    
        // loop till there are elements in the left and right runs
        while (i <= mid && j <= to) {
            if (A[i] < A[j]) {
                temp[k++] = A[i++];
            } else {
                temp[k++] = A[j++];
            }
        }
    
        // Copy remaining elements
        while (i <= mid) {
            temp[k++] = A[i++];
        }
    
        // Don't need to copy second half
    
        // copy back to the original array to reflect sorted order
        for (i = from; i <= to; i++) {
            A[i] = temp[i];
        }
    }
    
    // Iteratively sort array A[low..high] using temporary array
    public static void mergesort(int[] A)
    {
        int low = 0;
        int high = A.length - 1;
    
        // sort array A[] using temporary array temp
        int[] temp = Arrays.copyOf(A, A.length);
        //System.out.println("temp Array : " + Arrays.toString(temp));
    
        // divide the array into blocks of size m
        // m = [1, 2, 4, 8, 16...]
        for (int m = 1; m <= high - low; m = 2*m)
        {
            // for m = 1, i = 0, 2, 4, 6, 8...
            // for m = 2, i = 0, 4, 8, 12...
            // for m = 4, i = 0, 8, 16...
            // ...
            for (int i = low; i < high; i += 2*m)
            {
                int from = i;
                int mid = i + m - 1;
                int to = Integer.min(i + 2 * m - 1, high);
    
                if(mid<high) {
                    merge(A, temp, from, mid, to);
                }
    
            }
        }
    }
    
    // Iterative Implementation of Mergesort algorithm
    public static void main(String[] args)
    {
        int[] A = { 5, 7, -9, 3, -4, 2, 8, 8, 10, 11 };
    
        System.out.println("Original Array : " + Arrays.toString(A));
        mergesort(A);
        System.out.println("Modified Array : " + Arrays.toString(A));
    }
    
  2. # 2 楼答案

    你的中期计算不正确。您有时会将其设置在区域范围之外

    下面的更改通过防止mid越界来修复算法,类似于防止to越界

    int mid = i + m - 1;更改为int mid = Math.min(i + m - 1, A.length - 1);

    说明:正如您在评论中提到的,您正在检查的区域切片的大小正在增加。下面是数组的排序方式,以及发生越界错误的时间,以及为什么在2次方的大小上没有发生越界错误:

                 [ -9,  5,  7,  3, -4,  2,  8,  8, 10, 11 ]           Array size
     First pass:   []  []  []  []  []  []  []  []  []  []             1
         Second:   [    ]  [    ]  [    ]  [    ]  [    ]             2
          Third:   [            ]  [            ]  [       ERROR]     4