为什么我的合并排序比我的快速排序慢?
Why is my mergesort slower than my quicksort?
它们的时间复杂度相同,但是当我 运行 我对随机生成的包含 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.";
}
这是什么原因?是我的 quicksort/mergesort 不对还是归并排序在有大量随机数的链表上表现不好?或者别的什么?
谢谢!
您已经实现了一个可以执行所有操作的快速排序版本 "in-place",而您的合并排序会在每次递归调用时复制 left/right 的内容(merge()
也是如此)。这可能是造成差异的主要原因。
其次,就像上面评论中提到的 Luiggi - 你是如何进行基准测试的?你有适当的 JVM 预热吗?你 运行 有足够的周期并取平均值吗?使用 JVM 进行适当的基准测试可能很棘手:如果您没有使用它的经验,最好找一个 micro-benchmarking framework 并使用它!
它们的时间复杂度相同,但是当我 运行 我对随机生成的包含 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.";
}
这是什么原因?是我的 quicksort/mergesort 不对还是归并排序在有大量随机数的链表上表现不好?或者别的什么?
谢谢!
您已经实现了一个可以执行所有操作的快速排序版本 "in-place",而您的合并排序会在每次递归调用时复制 left/right 的内容(merge()
也是如此)。这可能是造成差异的主要原因。
其次,就像上面评论中提到的 Luiggi - 你是如何进行基准测试的?你有适当的 JVM 预热吗?你 运行 有足够的周期并取平均值吗?使用 JVM 进行适当的基准测试可能很棘手:如果您没有使用它的经验,最好找一个 micro-benchmarking framework 并使用它!