合并排序递归问题

huangapple go评论81阅读模式
英文:

Merge sort recursion trouble

问题

I've been trying to make a merge sort and I got the merging part down, it's just the recursive splitting that I'm having a little trouble with. The left and right lists are getting merged and sorted individually and not carrying over between each recursive pass. I'm not sure what I'm doing wrong with the recursion or how to fix it without scrapping the entire division method.

public static int[] mergeSort(int[] x)
{
    divide(x);
    return sorted;
}

public static void divide(int[] x)
{
    int midP;
    if((x.length/2f) == 1.5f) //the left side of the list will always be larger
        midP = 2;
    else 
        midP = x.length/2;

    if(midP == 0) //if the list contains one number end
        return;

    System.out.println("mid: " + midP);

    int[] left = new int[midP];
    int[] right = new int[x.length - midP];

    for(int i = 0; i < midP; i++) //fills the left list
        left[i] = x[i];

    for(int i = midP; i < x.length; i++) //fills the right list
        right[i-midP] = x[i];

    divide(left);
    divide(right);

    sorted = merge(left, right);
}

public static int[] merge(int[] x, int[] y)
{
    int[] mergedList = new int[x.length + y.length];

    int counter = 0, xCounter = 0, yCounter = 0, high = 0;

    while(xCounter < x.length && yCounter < y.length)
    {
        printArray(x);
        printArray(y);
        System.out.println("checking: " + x[xCounter] + " " + y[yCounter]);
        
        if(x[xCounter] < y[yCounter])
        {
            mergedList[counter] = x[xCounter];
            high = y[yCounter];
            if(xCounter != x.length)
                xCounter++;
        }
        else
        {
            mergedList[counter] = y[yCounter];
            
            high = x[xCounter];
            
            if(yCounter != y.length)
                yCounter++;
        }
        counter++;
    }
    mergedList[counter] = high;
    return mergedList;
}

public static void printArray(int[] x)
{
    System.out.print("list: ");
    for(int i = 0; i < x.length; i++)
        System.out.print(x[i] + " ");
    System.out.println();
}
英文:

I've been trying to make a merge sort and I got the merging part down, it's just the recursive splitting that I'm having a little trouble with. The left and right lists are getting merged and sorted individually and not carrying over between each recursive pass. I'm not sure what I'm doing wrong with the recursion or how to fix it without scrapping the entire division method.

public static int[] mergeSort(int[] x)
{
divide(x);
return sorted;
}
public static void divide(int[] x)
{
int midP;
if((x.length/2f) == 1.5f) //the left side of the list will always be larger
midP = 2;
else 
midP = x.length/2;
if(midP == 0) //if the list contains one number end
return;
System.out.println(&quot;mid: &quot; + midP);
int[] left = new int[midP];
int[] right = new int[x.length - midP];
for(int i = 0; i &lt; midP; i++) //fills the left list
left[i] = x[i];
for(int i = midP; i &lt; x.length; i++) //fills the right list
right[i-midP] = x[i];
divide(left);
divide(right);
sorted = merge(left, right);
}
public static int[] merge(int[] x, int[] y)
{
int[] mergedList = new int[x.length + y.length];
int counter = 0, xCounter = 0, yCounter = 0, high = 0;
while(xCounter &lt; x.length &amp;&amp; yCounter &lt; y.length)
{
printArray(x);
printArray(y);
System.out.println(&quot;checking: &quot; + x[xCounter] + &quot; &quot; + y[yCounter]);
if(x[xCounter] &lt; y[yCounter])
{
mergedList
0
+
网站访问量
= x[xCounter]; high = y[yCounter]; if(xCounter != x.length) xCounter++; } else { mergedList
0
+
网站访问量
= y[yCounter]; high = x[xCounter]; if(yCounter != y.length) yCounter++; } counter++; } mergedList
0
+
网站访问量
= high; return mergedList; } public static void printArray(int[] x) { System.out.print(&quot;list: &quot;); for(int i = 0; i &lt; x.length; i++) System.out.print(x[i] + &quot; &quot;); System.out.println(); }

答案1

得分: 0

使用递归方法时,像sorted这样的静态或实例变量使用起来比较棘手。问题在于,sorted在递归调用中会被设置和重置,很难预测在任何给定时间它的值会是什么。如果只使用局部变量,递归函数会更容易理解。所以,修改你的divide函数,让它返回已排序的数组,并使用递归调用的返回值:

public static int[] divide(int[] x) {
    ... 你现有的分割逻辑 ...

    int[] leftSorted = divide(left);
    int[] rightSorted = divide(right);

    return merge(leftSorted, rightSorted);
}

不要忘记同时修改主入口点:

public static int[] mergeSort(int[] x) {
    return divide(x);
}

merge方法中,似乎仍然存在一个错误:

int[] x = {5, 4, 1, 2, 3};
int[] sorted = mergeSort(x);

结果是 `1 2 3 4 0`
英文:

When using recursive methods, it's tricky to use static or instance variables like sorted in this case. What's happening is that sorted gets set and reset over the recursive calls, and it can be difficult to predict what its value will be at any given time. Recursive functions are easier to understand if you only use local variables. So change your divide function so that it returns the sorted array, and use the return value from the recursive calls:

public static int[] divide(int[] x) {
... your existing divide logic ...
int[] leftSorted = divide(left);
int[] rightSorted = divide(right);
return merge(leftSorted, rightSorted);
}

Don't forget to also change the main entry point:

public static int[] mergeSort(int[] x) {
return divide(x);
}

You seem to still have a bug in the merge method:

    int[] x = {5, 4, 1, 2, 3};
int[] sorted = mergeSort(x);

results in 1 2 3 4 0

huangapple
  • 本文由 发表于 2020年8月14日 00:53:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/63399813.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定