簡體   English   中英

有一種有效的“合並排序”功能,但不是完全可以,有人可以告訴我我做錯了什么嗎?

[英]Have a sort of working Merge Sort, but not quite, could someone tell me what I am doing wrong?

首先,我想從我的方法背后的推理開始。 我的想法是,我將輸入偶數或奇數的數組。 該數組將分解為原始數組長度的2D數組,每個索引的大小為1。 然后,我將繼續將索引合並在一起。 這適用於長度為2、4、8、16的長度。現在,由於3、5、6、7無效,我不得不稍微修改一下方法。 現在,我的問題是即使它們起作用,但並非所有情況都起作用。 例如,長度25不能正確返回。 下面是我的代碼:

/**
* A method to perform a merge sort
* @param array The array being fed in
*/
public static int[] mergeSort(int[] array)
{
  if (array.length == 1)
  {
     return array;
  }

  int size = array.length;
  int[][] miniArrayList = new int[size][1];

  for (int index = 0; index < array.length; index++)
  {
     miniArrayList[index][0] = array[index];
  }

  while (miniArrayList.length > 1)
  {
     if (miniArrayList.length % 2 == 0)
     {
        miniArrayList = mergeEven(miniArrayList);
     }
     else
     {
        miniArrayList[0] = mergeOdd(miniArrayList);
     }
  }
  return miniArrayList[0];
}

對於上述方法,我的想法是先輸入一個數組,將其分解,然后一點一點地合並該數組,直到獲得大小為1的排序數組為止。上面的方法調用以下方法:

private static int[][] mergeEven(int[][] array)
{
  int[][] tempSortList = new int[array.length / 2][];
  int tempIndex = 0;
  for (int index = 0; index < array.length; index += 2)
  {
     tempSortList[tempIndex] = merge(array[index], array[index + 1]);
     if (tempIndex != tempSortList.length)
     {
        tempIndex++;
     }
  }
  array = tempSortList;
  return array;
}

private static int[] mergeOdd(int[][] array)
{
  /**
   * The concept is to call the even merge method on the even part
   * of the list and then once I get to one array, I merge that array
   * with the extra array.
   */
  int[][] localArray = new int[array.length - 1][1];
  int[][] extra = new int[1][1];

  for (int index = 0; index < localArray.length; index++)
  {
     localArray[index][0] = array[index][0];
  }

  extra[0][0] = array[array.length - 1][0];

  int[][] tempSortList = new int[localArray.length / 2][];
  int tempIndex = 0;
  for (int index = 0; index < localArray.length; index += 2)
  {
     tempSortList[tempIndex] = merge(localArray[index], localArray[index + 1]);
     if (tempIndex != tempSortList.length)
     {
        tempIndex++;
     }
  }
  localArray = tempSortList;

  return localArray[0] = merge(localArray[0], extra[0]);
}

這很容易說明,但以防萬一。 由於數組為奇數或偶數,因此上述方法的排序方式有所不同。 最后,這些方法稱為實際的合並方法(我認為這種方法有效):

/**
* A merge method to merge smaller arrays to bigger
* arrays
* @param arrayOne The first array being fed in
* @param arrayTwo The second array being fed in
* @return A new integer array which is the sum of the
* length of the two arrays
*/
private static int[] merge(int[] arrayOne, int[] arrayTwo)
{
  /*
   * To make a proper method that deals with odd array sizes
   * look into seeing if it odd, only merging length of the array -1
   * and then once that is all merged merge that array with the last part of the array
   */
  //Creating the size of the new subarray
  int[] mergedArray;

  if (arrayOne.length % 2 == 0 && arrayTwo.length % 2 == 0)
  {
     int size = arrayOne.length;
     int doubleSize = 2 * size;
     mergedArray = new int[doubleSize];

     //Positions of each array
     int posOne = 0;
     int posTwo = 0;
     int mergeIndex = 0;

     while (posOne < size && posTwo < size)
     {
        if (arrayOne[posOne] < arrayTwo[posTwo])
        {
           mergedArray[mergeIndex] = arrayOne[posOne];
           mergeIndex++;
           posOne++;
        }
        else
        {
           mergedArray[mergeIndex] = arrayTwo[posTwo];
           mergeIndex++;
           posTwo++;
        }
     }

     if (posOne == size)
     {
        for (int rest = posTwo; rest < size; rest++)
        {
           mergedArray[mergeIndex] = arrayTwo[rest];
           mergeIndex++;
        }
     }
     else
     {
        for (int rest = posOne; rest < size; rest++)
        {
           mergedArray[mergeIndex] = arrayOne[rest];
           mergeIndex++;
        }
     }

  }
  else
  {
     int arrayOneSize = arrayOne.length;
     int arrayTwoSize = arrayTwo.length;
     int newArraySize = arrayOneSize + arrayTwoSize;
     mergedArray = new int[newArraySize];

     //Position in each array
     int posOne = 0;
     int posTwo = 0;
     int mergeIndex = 0;

     while (posOne < arrayOneSize && posTwo < arrayTwoSize)
     {
        if (arrayOne[posOne] < arrayTwo[posTwo])
        {
           mergedArray[mergeIndex] = arrayOne[posOne];
           mergeIndex++;
           posOne++;
        }
        else
        {
           mergedArray[mergeIndex] = arrayTwo[posTwo];
           mergeIndex++;
           posTwo++;
        }
     }
     if (posOne == arrayOneSize)
     {
        mergedArray[mergeIndex] = arrayTwo[posTwo];
        mergeIndex++;
     }
     else
     {
        for (int rest = posOne; rest < arrayOneSize; rest++)
        {
           mergedArray[mergeIndex] = arrayOne[rest];
           mergeIndex++;
        }
     }

  }

  return mergedArray;
}

所以我的問題是,無論我正確輸入任何數組大小,它都只能在某些大小上工作。 我已經閱讀了一些文章,但是我的實現方式與大多數我所看到的完全不同,這就是我在此處發布的原因。 我不想只復制工作正常的文件,而是想了解我做錯了什么,以便可以解決。 在此先感謝您的幫助!

您的問題在於merge的邏輯。 通過使用線

int size = arrayOne.length;

您假設兩個數組的長度相同。 但是,在不均勻的情況下,並非所有陣列都具有相同的長度。

將其更改為兩個不同的大小,代碼應該沒問題。

您更大的問題是您的算法過於復雜,更不用說對於大型數組而言效率低下。

我假設您是在進行學術活動,但是只要您能正常工作,請查看java.util.Arrays.mergeSort(私有方法)作為示例。

暫無
暫無

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

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