【问题标题】:Recursive Merge Sort递归合并排序
【发布时间】:2015-06-08 18:34:32
【问题描述】:

我正在尝试为类编写递归合并排序方法。当我尝试mergeSort(leftArr)mergeSort(rightArr) 时,我不断收到*s。为什么我的基本情况不起作用?

import java.util.Arrays;

public class SortingAlgorithms {
    public static void mergeSort(int[] list){

        int mid = list.length / 2;
        int [] leftArr = new int [mid];
        int [] rightArr;


        if (mid % 2 == 0) {
            rightArr = new int [mid];
        }
        else{
            rightArr = new int [mid + 1];
        }

        if (leftArr.length < 2 && rightArr.length < 2){
            list = mergeHelper(leftArr, rightArr);
        }

        // copying first half of array
        for (int i = 0; i < mid; i++){
            leftArr[i] = list[i];
        }

        // copying second half of array
        int placeHolder = 0;
        for (int i = mid; i < list.length; i++){
            if (placeHolder < rightArr.length) {
                rightArr[placeHolder] = list[i];
                placeHolder++;
            }
        }

        mergeSort(leftArr);
        mergeSort(rightArr);
    }

    public static int[] mergeHelper(int[] leftArr, int[] rightArr){

        int leftIndex = 0;
        int rightIndex = 0;
        int sortedArrayIndex = 0;
        int[] newList = new int[leftArr.length + rightArr.length];

        while (leftIndex < leftArr.length || rightIndex < rightArr.length){
            if (leftIndex < leftArr.length && rightIndex < rightArr.length){
                if(leftArr[leftIndex] > rightArr[rightIndex]){
                    newList[sortedArrayIndex] = rightArr[rightIndex];
                    rightIndex++;
                    sortedArrayIndex++;
                }
                else {
                    newList[sortedArrayIndex] = leftArr[leftIndex];
                    leftIndex++;
                    sortedArrayIndex++;
                }
            }

            else if (leftIndex < leftArr.length && rightIndex == rightArr.length){
                newList[sortedArrayIndex] = leftArr[leftIndex];
                leftIndex++;
                sortedArrayIndex++;
            }

            else if (rightIndex < rightArr.length && leftIndex == leftArr.length){
                newList[sortedArrayIndex] = rightArr[rightIndex];
                rightIndex++;
                sortedArrayIndex++;
            }
        }
        return newList;
    }

    public static void populateArray(int[] list){
        for (int i = 0; i < list.length; i++){
            list[i] = (int) ((Math.random() * 100));
        }
    }

    public static void main(String[] args){

        int [] list = new int [10];
        populateArray(list);
        System.out.println(Arrays.toString(list));
        mergeSort(list);
        System.out.println(Arrays.toString(list));


        //proof that mergeHelper() works
        //      int[] left =  {1,3,5,7,9};
        //      System.out.println(Arrays.toString(left));
        //      int[] right = {0,2,4,6,8};
        //      System.out.println(Arrays.toString(right));
        //      System.out.println(Arrays.toString(mergeHelper(left,right)));

}
}

【问题讨论】:

标签: algorithm sorting recursion merge stack-overflow


【解决方案1】:

你的 rightArr 长度确定不好。更正:

rightArr = new int [list.length - mid];

【讨论】:

    【解决方案2】:
    ## This is a way to use merge sort in c#, with recursion. ##
    
    
    
     static void Main(string[] args)
        {
            List<int> list = new List<int>();
            int m = int.Parse(Console.ReadLine());
            for (int i = 0; i < m; i++)
            {
                int p = int.Parse(Console.ReadLine());
                list.Add(p);
            }
            Console.WriteLine(String.Join(",", MergeSort(list)));
        }
        static List<int> MergeSort(List<int> array)
        {
            List<int> output = new List<int>();
            if (array.Count == 1)
            {
                return array;
            }
            if (array.Count == 2)
            {
                if (array[0] > array[1])
                {
                    int a = array[1];
                    array[1] = array[0];
                    array[0] = a;
                    return array;
                }
                else
                {
                    return array;
                }
            }
            else
            {
                List<int> firstList = new List<int>();
                List<int> secondList = new List<int>();
                for (int i = 0; i < array.Count / 2; i++)
                {   
                    firstList.Add(array[i]);
                    secondList.Add(array[i + array.Count / 2]);   
                }
                if (array.Count % 2 != 0)
                {
                    secondList.Add(array[array.Count - 1]);
                }
                firstList = MergeSort(firstList);
                secondList = MergeSort(secondList);
                int k = 0;
                int j = 0;
                int size = firstList.Count + secondList.Count;
                int markerFirst = firstList.Count;
                int markerSecond = secondList.Count;
    
                for (int i = 0; i < size; i++)
                {
                    if (k == markerFirst)
                    {
                        output.Add(secondList[j]);
                        j++;
                        continue;
                    }
                    if (j == markerSecond)
                    {
                        output.Add(firstList[k]);
                        k++;
                        continue;
                    }
                    if (firstList[k] < secondList[j])
                    {
                        output.Add(firstList[k]);
                        k++;
                    }
                    else
                    {
                        output.Add(secondList[j]);
                        j++;
                    }
                }
            }
            return output;
        }
    }
    
    }
    

    【讨论】:

      【解决方案3】:

      您的代码有一些问题:

      1) 在“mergeSort”方法中没有停止递归的条件,如下面的代码。您收到堆栈溢出,因为您的代码处于无限循环中。在“mergeSort”方法的第一行添加这段代码。

      if(list.length <= 1) 
          return;
      

      2) 修复“rightArr”大小...通过这 2 次更正,您的代码可以运行,但不能排序。

      int[] rightArr = new int [list.length - mid];
      
      //        if (mid % 2 == 0) {
      //            rightArr = new int[mid];
      //        } else {
      //            rightArr = new int[mid + 1];
      //        }
      

      以更简单的方式遵循代码...

      import java.util.Arrays;
      
      public class MergeSort {
      
          public static void main(String[] args) {
              Integer[] itens = {2,6,4,9,1,3,8,7,0};
      
              Integer[] tmp = new Integer[itens.length];
              int left = 0;
              int right = itens.length - 1;
      
              mergeSort(itens, tmp, left, right);
      
              System.out.println(Arrays.toString(itens));
          }
      
          private static void mergeSort(Integer[] itens, Integer[] tmpArray, int left, int right) {
      
              if(itens == null || itens.length == 0 || left >= right){
                  return;
              }
      
              int midle = (left + right) / 2;
      
              mergeSort(itens, tmpArray, left, midle);
              mergeSort(itens, tmpArray, midle + 1, right);
      
              merge(itens, tmpArray, left, midle + 1, right);
          }
      
          private static void merge(Integer[] itens, Integer[] tmpArray, int left, int right, int rightEnd) {
              int leftEnd = right - 1;
              int tmpIndex = left;
      
              while (left <= leftEnd && right <= rightEnd){
                  if (itens[left] < itens[right] ){
                      tmpArray[tmpIndex++] = itens[left++];
                  } else {
                      tmpArray[tmpIndex++] = itens[right++];
                  }
              }
      
              while (left <= leftEnd) { // Copy rest of LEFT half
                  tmpArray[tmpIndex++] = itens[left++];
              }
              while (right <= rightEnd) { // Copy rest of RIGHT half
                  tmpArray[tmpIndex++] = itens[right++];
              }
              while(rightEnd >= 0){ // Copy TEMP back
                  itens[rightEnd] = tmpArray[rightEnd--];
              }
          }
      }
      

      【讨论】:

      • 请描述您为解决提问者的问题所做的工作;就目前而言,没有解释的新代码并不能真正帮助任何人学习。
      • 代码有很多问题:1)没有条件像“IF(list.length