【问题标题】:Recursive Merge Sort Java Program递归合并排序Java程序
【发布时间】:2013-03-15 19:27:08
【问题描述】:

我一直在研究合并排序递归代码,但遇到了减速带。我在网上浏览了很多次,我的算法本身在纸上,但我似乎无法找出问题所在。

    public static int[] mergesort(int[] data, int low, int high)
    {
        int middle = (high+low)/2;
        if (middle==low)
        {
            int[] data2 = new int [1];
            data2[0]=data[middle];
            return data2;
        }
        else
        {
            int[] firstHalfSorted = mergesort(data, low, middle);
            int[] secondHalfSorted = mergesort(data, middle+1, high);
            return (merge(firstHalfSorted, secondHalfSorted));
        }
    }

    public static int[] merge(int[] firstHalfSorted, int[] secondHalfSorted)
    {
        int[] SortedArray = new int[firstHalfSorted.length+secondHalfSorted.length];
        int m = 0;
        int n = 0;
        int count = 0;
        while (m<firstHalfSorted.length && n<secondHalfSorted.length)
        {
            if (firstHalfSorted[m]>secondHalfSorted[n])
            {
                SortedArray[count]=secondHalfSorted[n];
                count++;
                n++;
            }
            else if (firstHalfSorted[m]<secondHalfSorted[n])
            {
                SortedArray[count]=firstHalfSorted[m];
                count++;
                m++;
            }
        }
        if (m!=firstHalfSorted.length)
        {
            while(m<firstHalfSorted.length){
                SortedArray[count]=firstHalfSorted[m];
                count++;
                m++;
            }
        }
        if (n!=secondHalfSorted.length)
        {
            while(n<secondHalfSorted.length){
                SortedArray[count]=secondHalfSorted[n];
                count++;
                n++;
            }
        }
        return SortedArray;
    }

这里有代码。问题来自一个带有数字的文本输入文件,3,9,7,2,10,5,1,8 按该顺序排列,代码只对其他数字进行排序,分别是 3,7 和 10,1,然后是 3, 7,1,10。

根据我的所有想法,它应该排序 3,9 然后 7,2 依此类推,然后是 3,9,7,2 和 10,5,1,8 依此类推,但事实并非如此!你们能帮帮我吗?

【问题讨论】:

  • 您的合并排序方法看起来不同/错误
  • 对我能做什么有什么想法吗?
  • 请只发布相关代码。在我看来,文件 I/O 没有问题。然后只需在代码中初始化示例数组并从代码示例中删除不相关的文件读/写代码。不相关的代码只是表明您不愿意为解决问题付出任何努力。
  • 编辑了与问题无关的代码。对不起!我相信这只是我的合并或合并排序方法的问题
  • main 方法对我来说没问题。我只是期待简单的初始化并在那里运行。

标签: java sorting recursion merge


【解决方案1】:

据我所知,有问题的代码是:

if (middle==low)
{
    int[] data2 = new int [1];
    data2[0]=data[middle];
    return data2;
}

high-low&lt;=1 时,此代码将返回一个元素数组。因此,对于 low = 0, high=1 方法,当它期望返回已排序的二元素数组时,它将返回第零个元素。您可以将其更改为:

if(low==high) //one element passed
//same here

【讨论】:

  • 好了!迷人的!非常感谢!
  • @MarcHosang 很高兴听到这个消息。如果您发现此答案有帮助,请考虑接受它(答案左侧有一个复选框)。在此查看faq
【解决方案2】:

你必须在这里改变以下两件事:

1) 将if (middle==low) 更改为if (high==low),如上一篇文章所述。

2) 将else if (firstHalfSorted[m] **&lt;** secondHalfSorted[n]) 更改为else if (firstHalfSorted[m] **&lt;=** secondHalfSorted[n]) 或简单地else

第二点很重要,因为目前您的代码不支持重复数字。换句话说,您的if-else 并不详尽,因为他们没有考虑firstHalfSorted[m]secondHalfSorted[n] 相等的情况。

【讨论】:

    【解决方案3】:

    对于合并排序,您只需将数据分成两部分,对这两部分进行递归,然后合并。不要试图通过找到中间或任何你想要做的事情来划分你的数据,而是将整个列表分成两半。

    例如:

    private int[] mergesort(int[] data) {
        int[] half1 = new int[data.length / 2];
        int[] half2 = new int[(data.length % 2 == 0)? data.length / 2 : data.length / 2 + 1];
        for (int i = 0; 2 * i < data.length; i++) {
            half2[i] = data[2 * i];
            if (2 * i + 1 < data.length) half1[i] = data[2 * i + 1];
        }
        int[] firstHalfSorted = mergesort(half1);
        int[] secondHalfSorted = mergesort(half2);
        return merge(firstHalfSorted, secondHalfSorted);
    }
    

    如果您想保留当前的方法(实际上看起来应该可行),您只需将if (middle == low) 更改为if (high == low) 来修复整数除法错误。

    【讨论】:

    • 嗯,我希望找到中间,然后将其拆分,然后在合并排序的每个实例上重复,直到它们只剩下一对,然后对每个实例进行排序就可以了。跨度>
    • 我想我明白你的意思了。也许你的问题是整数除法。如果 low 和 high 相差 1,则第一个案例将触发,这会丢失您要考虑的其他元素。相反,我会将您的支票更改为:if (data.length == 1)
    • 嗯,是的,第一个返回值是预期的 3,但是我希望 middle+1 变低,然后 low+high 将是另一个值。例如,2+3/2 = 2 然后 2+1+3/2 = 3
    • 不幸的是,这不适用于此算法。不要听起来忘恩负义!非常感谢您的帮助
    • 我不完全确定你的意思,但这就是为什么只有一半的数字被排序:考虑低 == 0 和高 == 1 的情况。因此我们正在考虑元素 0 和 1 .low + 1 / 2 = 0,所以 middle == 0. middle == low,所以我们返回一个仅包含第 0 个元素的数组。因此,元素 1 被完全遗忘了。
    【解决方案4】:

    这是一个简单的递归合并排序代码。

    public class solution {
    
     public static void merge(int[] input, int s, int e){
    
        int m = (s + e) / 2;
    
        int temp[] = new int[e - s + 1];
    
        int s1 = s;
        int s2 = m + 1;
    
        int i = s1;
        int j = s2;
        int p = 0;
        while(i <= m  && j <= e){
            if(input[i] > input[j]){
                temp[p] = input[j];
                j++;
                p++;
            }else{
                temp[p] = input[i];
                i++;
                p++;
            }
        }//end of while loop
    
        while(i <= m){
                temp[p] = input[i];
                p++;
                i++;
        }
        while(j <= e){
                temp[p] = input[j];
                p++;
                j++;
        }
    
        for(int k = 0; k < temp.length; k++){
            input[s + k] = temp[k];
        }
    }
    
    public static void callsort(int[] input, int s, int e){
    
        if(s >= e){
            return ;
        }
    
        int m = (s + e) / 2;
    
        callsort(input, s, m);
        callsort(input, m + 1, e);
        merge(input, s, e);
    
    }
    
    public static void mergeSort(int[] input){
        callsort(input , 0 , input.length - 1); 
    }
    }
    

    输入:5 6 3 2 1 4 输出:1 2 3 4 5 6

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-04-19
      • 2018-07-26
      • 2015-03-02
      • 1970-01-01
      • 2021-11-06
      • 2019-01-22
      相关资源
      最近更新 更多