【问题标题】:Mergesort Swaps and ComparisonsMergesort 交换和比较
【发布时间】:2012-07-29 21:07:19
【问题描述】:

我目前正在从事一个分析项目,我正在观察在 Java 中实现不同算法时的行为方式。我从网上得到了一些实现 Mergesort 算法的代码,现在我需要在一个由 10,000 个随机生成的整数(介于 1 到 100,000 之间)组成的数组上运行此代码,并记录进行了多少交换和比较。

我不确定在代码中的哪一点增加计算交换和比较的变量。期望值是多少?由于 Mergesort 的最佳、最差和平均情况都是 nlog(n),这是否意味着我应该期望交换和比较的总和为 10,000*(log base 2 of 10,000) 大约 = 138,000?

这是代码,我猜只有在更改原始数组时才会发生交换,比较我不太确定:

void MergeSort(int low, int high)
   // a[low : high] is a global array to be sorted.
// Small(P) is true if there is only one element to
// sort. In this case the list is already sorted.
{
   if (low < high) { // If there are more than one element
          // Divide P into subproblems.
          // Find where to split the set.
          int mid = (low + high)/2;
          // Solve the subproblems.
          MergeSort(low, mid);
          MergeSort(mid + 1, high);
          // Combine the solutions.
          Merge(low, mid, high);
   }
}

   void Merge(int low, int mid, int high)
 // a[low:high] is a global array containing two sorted
 // subsets in a[low:mid] and in a[mid+1:high]. The goal
 // is to merge these two sets into a single set residing
 // in a[low:high]. b[] is an auxiliary global array.
 {
     int h = low, i = low, j = mid+1, k;
   while ((h <= mid) && (j <= high)) {
      if (a[h] <= a[j]) { b[i] = a[h]; h++; }
      else { b[i] = a[j]; j++; } i++;
   }
   if (h > mid) for (k=j; k<=high; k++) {
                   b[i] = a[k]; i++;
                }
   else for (k=h; k<=mid; k++) {
           b[i] = a[k]; i++;
        }
   for (k=low; k<=high; k++) a[k] = b[k];

}

【问题讨论】:

  • 您好!每个 if() 语句都是比较,如果你说 b[i] = a[k],它就是一个交换。您需要计算这些操作执行了多少次。
  • while 或 for 循环中的操作是否也算作比较?例如,如果你有 while(i0) 每次循环时都会算作比较吗?事实上,它是否算作两次比较,因为如果第一个不为假,您可能需要同时评估它们?

标签: java algorithm mergesort


【解决方案1】:

我不确定在代码中的哪一点增加计算交换和比较的变量。

我建议您为交换和比较操作创建辅助方法。这将为您提供增量计数器代码的好地方。

由于 Mergesort 的最佳、最差和平均情况都是 nlog(n),这是否意味着我应该期望 10,000(10,000 的对数基数 2)大约 = 138,000交换和比较的总和?*

您可以预期的是,比较次数与 n log(n) 成正比,其中输入的大小为 n

【讨论】:

  • 没有明确的交换和比较操作,我不确定如何实现辅助方法。你关于比例的第二点是我不知道的。但这意味着什么?比例可以是主观的,就一些常数而言的比例?到目前为止,我的结果是交换保持稳定的 133616 计数,而比较在 130463 左右变化。这与原始复杂度成比例大约为 2nlog(n)。
  • boolean compare(int a, int b) { compareCount++; return a &lt; b; }void swap(int i, int j) { swapCount++; int tmp = arr[i]; arr[i] = arr[j]; arr[j] = tmp; }
  • 如果我们有兴趣找到每个元素的交换次数怎么办?我们可以在这个算法中计算元素交换吗?
【解决方案2】:

在您的合并函数中,我添加了一个变量计数,它将包含完成的总交换次数

  while ((h <= mid) && (j <= high)) {
      if (a[h] <= a[j]) { b[i] = a[h]; h++; }
      else { b[i] = a[j]; j++; count+=mid-h+1; } i++;
  }

【讨论】:

    【解决方案3】:

    我实际上是在为算法和数据结构中的作业做这个。线程有点尘土飞扬,但对于任何可以使用它的人来说,这就是我得到的:

    在您的合并方法中

    while ((h <= mid) && (j <= high)) {
      if (a[h] <= a[j]) { b[i] = a[h]; h++; }
      else { b[i] = a[j]; j++; } i++;
    }
    

    if 语句是进行比较的地方,我几乎想说,即使你对 else 语句进行比较,也会因为 if 语句失败而进行比较。

    else 语句是开始进行交换的地方,如果您在 else 语句中放置一个计数器,它将计算所有交换。我通过两次检查数组来确认这一点,一次是未排序的,另一次是排序的。我对此不是 100%,所以任何反馈都表示赞赏。在我的作业中更容易看到,因为我正在对字符串进行排序,这些与上面发布的 Merge 函数中的行相同,来自我的作业:

    while(leftPos<=leftEnd && rightPos<=rightEnd)
    {
        mergeSortComparisons++;
    
        if (a[leftPos].compareTo(a[rightPos]) <= 0)     
            tmpArray[tmpPos++]=a[leftPos++];
    
        else 
        {
            tmpArray[tmpPos++]=a[rightPos++];
            mergeSortSwaps++;
        }
    }
    

    mergeSortSwaps 和 mergeSortComparisons 是在构造函数中设置的类变量。如果我记得方法,我可以重置它们。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-09-29
      • 2012-03-10
      • 2011-05-11
      • 2013-10-27
      • 2021-03-09
      • 1970-01-01
      • 1970-01-01
      • 2020-11-10
      相关资源
      最近更新 更多