【问题标题】:Why is my mergesort slower than my quicksort?为什么我的合并排序比我的快速排序慢?
【发布时间】:2015-06-25 16:44:27
【问题描述】:

它们的时间复杂度相同,但是当我在一个随机生成的包含 100,000 个条目的链表上运行合并排序时:

public LinkedList<Integer> linkedListSort(LinkedList<Integer> list) {
    if (list.size() <= 1) return list;
    LinkedList<Integer> left = new LinkedList<Integer>();
    LinkedList<Integer> right = new LinkedList<Integer>();
    int middle = list.size()/2;
    for (int i = 0; i < middle; i++) {
        left.add((int)list.get(i)); steps++;
    }
    for (int i = middle; i < list.size(); i++) {
        right.add((int)list.get(i)); steps++;
    }
    left = linkedListSort(left);
    right = linkedListSort(right);
    return merge(left, right);
}

public LinkedList<Integer> merge(LinkedList<Integer> left, LinkedList<Integer> right) {
    LinkedList<Integer> result = new LinkedList<Integer>();
    while (!(left.isEmpty()) && !(right.isEmpty())) {
        steps++;
        if ((int)left.peekFirst() <= (int)right.peekFirst()) {
            result.add(left.poll());
        } else {
            result.add(right.poll());
        }
    }
    while (!(left.isEmpty())) {result.add(left.poll()); steps++;}
    while (!(right.isEmpty())) {result.add(right.poll()); steps++;}
    return result;
}

这比我的快速排序慢很多:

public String arraySort(int[] array, int startIndex, int endIndex, int steps) {
    int leftIndex = startIndex;
    int rightIndex = endIndex;
    int pivot = array[(leftIndex + rightIndex) / 2];
    while (leftIndex <= rightIndex) {
        steps++;
        //search for an element with a higher value than the pivot, lower than it
        while (array[leftIndex] < pivot) {steps++; leftIndex++;}
        //search for an element with a lower value than the pivot, higher than it
        while (array[rightIndex] > pivot) {steps++; rightIndex--;}
        //check the left index hasn't overtaken the right index
        if (leftIndex <= rightIndex) {
            //swap the elements
            int holder = array[leftIndex];
            array[leftIndex] = array[rightIndex]; 
            array[rightIndex] = holder;
            leftIndex++; rightIndex--;
        }
    }
    if (leftIndex < endIndex) arraySort(array, leftIndex, endIndex, steps); 
    if (rightIndex > startIndex) arraySort(array, startIndex, rightIndex, steps);
    return "Quicksort on an unsorted array took " + steps + " steps.";
}

这是什么原因?我的快速排序/合并排序不是应该的,还是合并排序在具有大量随机数的链表上表现不佳?还是别的什么?

谢谢!

【问题讨论】:

  • 你如何测量每个的速度?您是在使用微基准测试框架,还是天真地一个接一个地执行?
  • 为什么你认为合并排序比快速排序更快?
  • @LuiggiMendoza 我没有正确测量它,但我必须等待至少 10 秒才能完成合并排序,但我的快速排序不会花费很多时间。此外,我一直在测量每个 on 进行的比较量,快速排序大约需要 75000 次,合并排序需要 3337856 次。
  • @ErlangBestLanguage 这不是时间复杂度告诉你的,不完全是。还有许多其他因素,包括时间复杂度本身的隐藏常数。不过,在这种情况下,您期望有相当的性能是正确的。
  • 因为如果对输入进行排序,这种快速排序将只进行比较,不进行交换。非常快。

标签: java sorting time-complexity quicksort mergesort


【解决方案1】:

您已经实现了一个快速排序版本,它“就地”完成所有操作,而您的合并排序在每次递归调用时复制左/右的内容(与 merge() 相同)。这可能是造成差异的主要原因。

第二,就像上面 cmets 中提到的 Luiggi - 你如何进行基准测试?你得到了适当的 JVM 预热吗?您是否运行足够的周期并取平均值?使用 JVM 进行适当的基准测试可能会很棘手:如果您没有使用它的经验,最好找一个 micro-benchmarking framework 并使用它!

【讨论】:

  • 这实际上是一个好点,我会重新考虑我是如何做我的归并排序的!谢谢!此外,我还没有涉足任何适当的基准测试,这主要是因为执行时间明显更长,但我会调查一下,谢谢!
猜你喜欢
  • 2021-06-19
  • 2021-06-06
  • 2010-10-04
  • 2021-12-09
  • 1970-01-01
  • 1970-01-01
  • 2011-06-02
  • 2017-03-18
  • 2018-11-14
相关资源
最近更新 更多