为什么我的堆排序比Java和C ++的排序函数更快?

时间:2013-11-14 22:27:04

标签: java c++ sorting

我最近学会了如何使用堆和heapsort的美丽。我决定将heapsort与C ++中的std :: sort和Java中的Arrays.sort()进行比较。我整理了一个整数数组,每个整数随机生成的范围为< 0; 20亿)

我在Java中生成100,000,000个整数到一个数组中,然后运行Arrays.sort(),然后生成新的随机序列并运行我的heapSort()。这是我的Java程序的输出:

Arrays.sort time: 10.923 seconds.

Heap sort time: 1.402 seconds.

所以heapsort的速度提高了约8倍。

然后我在C ++中运行类似的代码,这次使用std :: vector作为我的容器(由于std :: sort需要两个迭代器)。

C ++结果:

Heapsort: 3.213

std::sort: 37.264

所以在我的程序中,std :: sort大约慢了12倍。

在Java中,我使用System.currentTimeMilis()测量时间,在C ++中我使用了clock()。

这是在Windows 7,四核Intel i5 2500k上测试的,超频到4.8GHz。 C ++是用-Wall -pedantic标志编译的。

谁能告诉我发生了什么事? heapsort真的那么快吗?或者我在代码中犯了错误?我不想用很多代码来填充这篇文章,所以我会在这篇文章的末尾链接它。

顺便说一句:是的,我知道Arrays.sort()是稳定的,而heapsort则不是。 Java没有不稳定的排序(至少,我还没有找到)。这就是我在C ++中使用std :: sort的原因,看看它是否与稳定性有关。

源代码,包括C ++和Java:https://gist.github.com/anonymous/7475399

3 个答案:

答案 0 :(得分:8)

你的Java代码看起来对我来说是错误的

int tmp = heap[0];
heap[i] = heap[0];
heap[i] = tmp;

这不是交换两个元素的代码。

这会对执行时间产生影响吗?我不知道堆的排序是否足以确定。

答案 1 :(得分:2)

您没有正确地交换Java中的项目(如john指出的那样),也没有正确交换C ++代码中的项目:

void heapSort(vector<int> & heap, int length)
{
    int heapsize = length;
    buildHeap(heap, heapsize);
    for(int i = heapsize-1; i >= 1; i--)
    {
        int tmp = heap[0];
        heap[i] = heap[0];
        heap[i] = tmp; // overwrote the item you just tried to swap!
        heapsize--;
        heapify(heap, 0, heapsize);
    }
}

简而言之,您的代码“效率更高”,因为它根本不进行任何排序。

答案 2 :(得分:1)

您的C ++代码中还有一个问题与您如何生成随机分布有关:

int randomval()
{
  double d;
  int result;
  d = rand() / RAND_MAX;
  result = (int) (d * N);
  return result;
}

d始终为0,因为您执行了int除法,然后隐含地将其转换为double。简而言之,您的randomval函数根本没有给您任何随机值。

使用自己的堆排序对此进行排序时,始终会执行相同的代码路径。在您的情况下,heapify可能永远不会执行这部分代码:

if (largest != i)
{
    int tmp = heap[i];
    heap[i] = heap[largest];
    heap[largest] = tmp;

    heapify(heap, largest, heapsize);
}

这就是为什么您的实现出现更快。

使用实际分布修复随机测试数据我认为您会发现实施速度较慢:

#include <random>
// snip...
int main()
{
  int length = 10000000;
  std::vector<int> vint1;

  std::default_random_engine gen;
  std::uniform_int_distribution<int> randomval(1, N);
  for (int i = 0; i < length; i++)
  {
        vint1.push_back(randomval(gen));
  }
  std::vector<int> vint2 = vint1; /* so we're sorting same testdata for both */
  // ...

再次重新启动基准显示:

g++ -std=c++0x -Wall -pedantic -O2 heapsorttest.cpp -o heapsorttest.exe
heapsorttest.exe

Heapsort: 5.822s
true

std::sort: 0.936s
true