【问题标题】:How to implement a k-way merge sort?如何实现k路归并排序?
【发布时间】:2018-04-12 23:01:04
【问题描述】:

我需要实现一个函数,它对未排序的数组或整数进行 k 路合并排序。

该函数有两个参数,一个整数K,它是排序的“方式”,总是2的幂。第二个参数是要排序的整数数组,其长度也是2的幂.

函数是返回一个包含排序元素的数组。到目前为止,我知道如何实现常规合并排序。我将如何修改此代码以实现 K 路合并排序? (注意:这个函数不返回排序后的数组,我也需要帮助。它也不接受 K,因为它是一个常规的合并排序)

以下代码:

public class MergeSort {

  public static void main(String[] args) {

  }

  public static void mergeSort(int[] inputArray) {
    int size = inputArray.length;
    if (size < 2)
        return;
    int mid = size / 2;
    int leftSize = mid;
    int rightSize = size - mid;
    int[] left = new int[leftSize];
    int[] right = new int[rightSize];
    for (int i = 0; i < mid; i++) {
        left[i] = inputArray[i];

    }
    for (int i = mid; i < size; i++) {
        right[i - mid] = inputArray[i];
    }
    mergeSort(left);
    mergeSort(right);
    merge(left, right, inputArray);
  }

  public static void merge(int[] left, int[] right, int[] arr) {
    int leftSize = left.length;
    int rightSize = right.length;
    int i = 0, j = 0, k = 0;
    while (i < leftSize && j < rightSize) {
      if (left[i] <= right[j]) {
        arr[k] = left[i];
        i++;
        k++;
      } else {
        arr[k] = right[j];
        k++;
        j++;
      }
    }
    while (i < leftSize) {
      arr[k] = left[i];
      k++;
      i++;
    }
    while (j < leftSize) {
      arr[k] = right[j];
      k++;
      j++;
    }
  }
}

【问题讨论】:

  • 您认为“k-way 归并排序”到底是什么?您提出的问题实际上并没有多大意义,因为修改合并排序以使其使用 k 路合并没有特别的优势。 2 路合并已经是该算法的最佳选择。
  • @Jim Mischel 也许 - 准备外部排序学习。
  • @MBo:但这是完全不同的东西,充其量与归并排序有一种随意的关系。您不会修改合并排序来创建外部排序。无论如何,他的问题一点都不清楚。
  • @MBo 对不起,如果我不清楚。让我概述一下我需要采取的步骤。输入数组的元素分布在其他 K 个大小为 n/K 的数组中。然后我需要在每个 K 数组上递归调用我的 kwaymergesort 函数,并跟踪返回的数组。然后我需要将这些数组合并成一个大小为 n 的数组,并进行排序。
  • @Mr. Pickles 你熟悉通常的归并排序吗?我没有检查您的代码,但 merge 函数看起来正确

标签: java arrays algorithm sorting mergesort


【解决方案1】:

常规归并排序是双向排序。您比较数组前半部分和后半部分的元素并将最小的元素复制到输出数组。

对于 k 路排序,您将输入数组划分为 K 个部分。 K 个索引指向每个部分的第一个元素。为了有效地选择其中最小的元素,请使用优先级队列(基于二叉堆)并在每一步从堆顶弹出最小的元素。当您弹出属于第 m 部分的元素时,从同一部分推送下一个元素(如果它仍然存在)

让你的数组长度为 16 且 k = 4。
第一个递归级别为从索引 0..3、4..7、8..11、12..15 复制的数组调用 4 个合并排序。
第二个递归级别获取长度为 4 的数组,并为 1 元素数组调用 4 个合并排序。
第三个递归级别获取长度为 1 的数组并立即返回(这样的数组已排序)。
现在在第二个递归级别,您将 4 个单元素数组合并为一个排序数组。
现在在第一个递归级别,您将 4 个四元素数组合并为一个长度为 16 的排序数组

【讨论】:

  • 如果实现为 bottom up merge sort ,通用的 k 路合并排序会更简单。假设使用索引进行了合理优化的合并排序,自上而下必须在递归期间将生成的索引推入/弹出堆栈,而自下而上则跳过所有递归并在每个 k 路合并过程中使用迭代来推进 k 个索引。
猜你喜欢
  • 1970-01-01
  • 2021-04-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多