了解Java中合并排序算法的关键操作计数

时间:2016-10-15 11:54:52

标签: java algorithm sorting

我正在评估合并排序算法并计算关键操作。虽然从技术上讲这是作业,但它来自先前的作业,而代码是按比例缩小的版本,仅显示相关区域。我正在努力更好地理解我的问题并调试我的关键操作计数以准确描绘。

该项目是实施Merge Sort并对其进行评估。关注的领域是计算关键操作并通过随机填充10个不同大小的阵列来确定计数的偏差,每个大小运行50次不同的时间(具有不同的随机数据)。我的发现是,对于每个大小,关键操作的数量总是相同(例如,无论数据如何,大小为10的阵列都会进入68个关键操作),使关键操作偏差为0。

教授说这是不准确的,我的程序有问题,因为它应该为每个数组长度的不同数据产生不同的计数。我试图弄清楚我的程序中的哪些内容不准确导致此问题。我已经检查过每个传递产生不同的数组数据,并且这些数据被传递给排序算法并正确排序。

下面是我写的代码,再次,无论数据如何,它仍会产生相同的关键操作计数。任何人都可以指出我的问题吗?无论我对伯爵做什么,它总能产生相同的价值。

public class MergeSortSingle {
public static int count = 0;

private MergeSortSingle() { }

private static void merge(Comparable[] a, Comparable[] aux, int lo, int mid, int hi) {

    // copy to aux[]
    for (int k = lo; k <= hi; k++) {
        count++;
        aux[k] = a[k]; 
    }

    // merge back to a[]
    int i = lo, j = mid+1;
    for (int k = lo; k <= hi; k++) {
        if      (i > mid) {
            count++;
            a[k] = aux[j++];
        }
        else if (j > hi) {
            count++;
            a[k] = aux[i++];
        }
        else if (less(aux[j], aux[i])) {
            count++;
            a[k] = aux[j++];
        }
        else      {
            count++;
            a[k] = aux[i++];
        }
    }
}

private static void sort(Comparable[] a, Comparable[] aux, int lo, int hi) {
    if (hi <= lo) return;
    int mid = lo + (hi - lo) / 2;
    sort(a, aux, lo, mid);
    sort(a, aux, mid + 1, hi);
    merge(a, aux, lo, mid, hi);
}

public static void sort(Comparable[] a) {
    Comparable[] aux = new Comparable[a.length];
    sort(a, aux, 0, a.length-1);
}

private static boolean less(Comparable v, Comparable w) {
    return v.compareTo(w) < 0;
}

private static void show(Comparable[] a) {
    System.out.println("\nAfter Sorting completed:");
   System.out.print(Arrays.toString(a));
   System.out.println();
}

public static void main(String[] args) {
    int length = 10;
    Comparable[] a = new Comparable[length];
    for (int w = 0; w < length; w++) {
            a[w] = (int) (Math.random() * 10000 + 1);
        }
    System.out.println("Before Sorting:");
    System.out.print(Arrays.toString(a));
    System.out.println();
    MergeSortSingle.sort(a);
    show(a);
    System.out.println("\nCounter = " + count);
}
}

示例输出1:

排序前: [9661,4831,4865,3333,1451,3029,5258,4788,9463,8971]

排序完成后: [1451,3029,3333,4788,4831,4865,5258,8971,9463,9661]

计数器= 68

示例输出2:

排序前: [9446,230,9089,7865,5829,2589,4068,5608,6138,372]

排序完成后: [230,372,2589,4068,5608,5829,6138,7865,9089,9446]

计数器= 68

合并排序代码来自: http://algs4.cs.princeton.edu/22mergesort/Merge.java.html

1 个答案:

答案 0 :(得分:1)

您只需在合并子数组时进行计数 - 您使用计数器复制数组aux - 这将始终是相同数量的操作,然后您再次在{{1}使用它}循环 - 你有4条路径,每条路径都会递增计数器 - 再次固定次数 你必须在for - sort计算同志事件 - 这是一项行动。如果它失败了 - 这是另一个操作。