【问题标题】:What's wrong with my merge sort implementation?我的合并排序实现有什么问题?
【发布时间】:2020-09-05 15:35:08
【问题描述】:
// merge operation for merge sort
private static void merge(int[] a, int left, int middle, int right) {
    int[] temp = new int[right - left + 1];        
    int leftCrawler = left, rightCrawler = middle;
    int currentIndex = 0;

    while (leftCrawler < middle && rightCrawler <= right) {
        if (a[leftCrawler] < a[rightCrawler])
            temp[currentIndex++] = a[leftCrawler++];
        else
            temp[currentIndex++] = a[rightCrawler++];
    }

    while (leftCrawler < middle)
        temp[currentIndex++] = a[leftCrawler++];

    while (rightCrawler <= right)
        temp[currentIndex++] = a[rightCrawler++];

    // copy temp into a
    for (int i = 0; i < temp.length; i++)
        a[i] = temp[i];
}

private static void mergeSort(int[] a, int left, int right) {
    if (right > left) {
        int middle = left + (right - left) / 2;
        mergeSort(a, left, middle);
        mergeSort(a, middle + 1, right);
        merge(a, left, middle, right);
    }
}

public static void mergeSort(int[] a) {
    int left = 0, right = a.length - 1;
    mergeSort(a, left, right);
}

所以,我认为问题可能出在我的合并操作上,但是我在以下数组 int[] a = {2, 5, 7, 15, 8, 9, 10}left = 0middle = 4right = a.length - 1 上对其进行了测试,合并操作完成了它需要成功的操作.

我已经将我的 mergeSort 实现与各种网站上的实现进行了比较,但我看不出有什么不同。我的 mergeSort 不会成功地对数组进行排序。我做错了什么?

【问题讨论】:

    标签: java algorithm sorting mergesort


    【解决方案1】:

    您的代码中有 3 个错误:

    • 合并循环不包含a[middle] 处的元素,因为您使用leftCrawler &lt; middle 而不是:

        while (leftCrawler <= middle && rightCrawler <= right)
      
    • 第二个循环while (leftCrawler &lt; middle)也必须改为:

        while (leftCrawler <= middle)
      
    • temp 复制回a 的循环在a 中使用了不正确的索引。应该是:

            // copy temp into a
            for (int i = 0; i < temp.length; i++)
                a[left + i] = temp[i];
      

    请注意,第一个错误源于此处使用的有害约定,其中 rightmiddle 包含在切片中而不是排除在外。排除正确的边界允许更简单的代码,而不会出现任何容易出错的+1/-1 调整。

    这是修改后的版本:

    // merge operation for merge sort
    private static void merge(int[] a, int left, int middle, int right) {
        int[] temp = new int[right - left];        
        int leftCrawler = left, rightCrawler = middle;
        int currentIndex = 0;
    
        while (leftCrawler < middle && rightCrawler < right) {
            if (a[leftCrawler] < a[rightCrawler])
                temp[currentIndex++] = a[leftCrawler++];
            else
                temp[currentIndex++] = a[rightCrawler++];
        }
    
        while (leftCrawler < middle)
            temp[currentIndex++] = a[leftCrawler++];
    
        while (rightCrawler < right)
            temp[currentIndex++] = a[rightCrawler++];
    
        // copy temp into a
        for (int i = 0; i < temp.length; i++)
            a[left + i] = temp[i];
    }
    
    private static void mergeSort(int[] a, int left, int right) {
        if (right - left >= 2) {
            int middle = left + (right - left) / 2;
            mergeSort(a, left, middle);
            mergeSort(a, middle, right);
            merge(a, left, middle, right);
        }
    }
    
    public static void mergeSort(int[] a) {
        mergeSort(a, 0, a.length);
    }
    

    【讨论】:

      【解决方案2】:

      问题可能出在您的副本上:

          // copy temp into a
          for(int i = 0; i < temp.length; i++)
              a[i] = temp[i];
      

      你可能想要的是(注意left + i):

          // copy temp into a
          for(int i = 0; i < temp.length; i++)
              a[left + i] = temp[i];
      

      (您的测试未检测到问题,因为left 为 0。)

      【讨论】:

      • 我进行了更改,我的输入数组保持不变。我承认此更改是必要的,但我仍然没有对数组进行排序。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多