我手工制作的heapsort
似乎比JavaScript的内置排序例程更快,在Chromium 45.02454.101和Firefox 41.0.2中,在Intel i5上运行在Ubuntu 14.04 LTS上
由于我怀疑自己已经实施了世界级的排序程序,因此我不清楚其原因可能是什么。
为了允许再现这种现象,这里所有的代码都是:
<!doctype html>
<html>
<head>
<title>Sorting Runtime</title>
<meta charset="utf-8">
<style>
#output {
background-color: #EEEEEE;
padding: 1ex;
}
#output p {
font-family: monospace;
margin: 0;
}
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script>
"use strict";
var actualCode = function () {
var ary;
var dataSizes = [1000, 2000, 4000, 8000, 16000, 32000, 64000, 128000, 256000];
var sortingFunctions = [
{ name: "built-in sort", fn: function (ary) { ary.sort (); } },
{ name: "heapsort", fn: function (ary) { heapsort (ary); } }
];
var runsPerDataSize = 10;
sortingFunctions.forEach (function (f) {
print (f.name);
var s = f.fn;
dataSizes.forEach (function (dataSize) {
var nRun, ary;
var masterAry = buildAry (dataSize);
var profilingStart = new Date().getTime();
for (nRun = 0; nRun < runsPerDataSize; ++nRun) {
ary = masterAry.slice (); // copy
s (ary); // sort
if (!checkSorted(ary)) { print ("Not sorted!"); }
}
var profilingElapsed = new Date().getTime() - profilingStart;
print ("Number of items: " + dataSize + " -- Time needed (in milliseconds): " + profilingElapsed / runsPerDataSize);
})
});
function heapify (ary) {
var i;
var arylen = ary.length;
for (i = 1; i < arylen; ++i) {
repairUpwards (ary, i);
}
}
function fillVacancy (ary, arylen) {
var first, second;
var i = 0;
while (true) {
first = (i << 1) + 1;
second = first + 1;
if (first >= arylen) { return i; }
if (second >= arylen) {
ary [i] = ary [first];
return first;
}
if (ary [first] > ary [second]) {
ary [i] = ary [first];
i = first;
} else {
ary [i] = ary [second];
i = second;
}
}
}
function repairUpwards (ary, fromIndex) {
var parent, tmp;
var i = fromIndex;
while (i > 0) {
parent = (i-1) >> 1;
if (ary [parent] < ary [i]) {
tmp = ary [parent]; ary [parent] = ary [i]; ary [i] = tmp;
} else {
return;
}
i = parent;
}
}
function heapsort (ary) {
var tmplast, newVacancy;
heapify (ary);
var arylen = ary.length;
var nRemaining = arylen;
while (nRemaining > 1) {
tmplast = ary [nRemaining - 1];
ary [nRemaining - 1] = ary [0];
newVacancy = fillVacancy (ary, nRemaining - 1);
ary [newVacancy] = tmplast;
repairUpwards (ary, newVacancy);
--nRemaining;
}
}
function checkSorted (ary) {
var i;
for (i = ary.length - 1; i > 0; --i) {
if (ary [i] < ary [i-1]) { return false; }
}
return true;
}
function buildAry (dataSize) {
var ary = [];
var i;
for (i = dataSize - 1; i >= 0; --i) ary.push (Math.random ());
return ary;
}
};
// user interface
var outputDivLogger = {
reset : function () { $('#output').empty (); },
log : function (msg) {
var p = $('<p />').text (msg);
$('#output').append (p);
}
};
var print = function (msg) {
outputDivLogger.log (msg);
};
var run = function () {
outputDivLogger.reset ();
try {
actualCode ();
} catch (e) {
outputDivLogger.log (String(e));
}
};
$(document).ready (function () {
$("#btnStart").click (function () {
run ();
});
outputDivLogger.log ("[No output yet.]")
});
</script>
</head>
<body>
<h2>Measuring Sorting Speed</h2>
<div class="content">
<form>
<p><input type="button" id="btnStart" value="Run"></p>
</form>
</div>
<h3>Output</h3>
<div class="content">
<div id="output"></div>
</div>
</body>
</html>
示例输出(Firefox):
built-in sort
Number of items: 1000 -- Time needed (in milliseconds): 0.8
Number of items: 2000 -- Time needed (in milliseconds): 1.5
Number of items: 4000 -- Time needed (in milliseconds): 2.8
Number of items: 8000 -- Time needed (in milliseconds): 4.9
Number of items: 16000 -- Time needed (in milliseconds): 8.5
Number of items: 32000 -- Time needed (in milliseconds): 14.9
Number of items: 64000 -- Time needed (in milliseconds): 31.3
Number of items: 128000 -- Time needed (in milliseconds): 68.9
Number of items: 256000 -- Time needed (in milliseconds): 168.7
heapsort
Number of items: 1000 -- Time needed (in milliseconds): 0.2
Number of items: 2000 -- Time needed (in milliseconds): 0.2
Number of items: 4000 -- Time needed (in milliseconds): 0.4
Number of items: 8000 -- Time needed (in milliseconds): 0.8
Number of items: 16000 -- Time needed (in milliseconds): 1.6
Number of items: 32000 -- Time needed (in milliseconds): 3.5
Number of items: 64000 -- Time needed (in milliseconds): 7.6
Number of items: 128000 -- Time needed (in milliseconds): 16.5
Number of items: 256000 -- Time needed (in milliseconds): 34.9
编辑:在下面的一条评论中,有人指出
ary.sort ();
应替换为
ary.sort (function (a, b) { return a - b; });
这确实改善了内置排序的结果,但它仍然较慢:
火狐
built-in sort
Number of items: 1000 -- Time needed (in milliseconds): 0.3
Number of items: 2000 -- Time needed (in milliseconds): 0.4
Number of items: 4000 -- Time needed (in milliseconds): 0.8
Number of items: 8000 -- Time needed (in milliseconds): 1.8
Number of items: 16000 -- Time needed (in milliseconds): 3.5
Number of items: 32000 -- Time needed (in milliseconds): 6.5
Number of items: 64000 -- Time needed (in milliseconds): 10.9
Number of items: 128000 -- Time needed (in milliseconds): 21.8
Number of items: 256000 -- Time needed (in milliseconds): 49.9
heapsort
Number of items: 1000 -- Time needed (in milliseconds): 0.3
Number of items: 2000 -- Time needed (in milliseconds): 0.2
Number of items: 4000 -- Time needed (in milliseconds): 0.3
Number of items: 8000 -- Time needed (in milliseconds): 0.7
Number of items: 16000 -- Time needed (in milliseconds): 1.6
Number of items: 32000 -- Time needed (in milliseconds): 3.4
Number of items: 64000 -- Time needed (in milliseconds): 7.3
Number of items: 128000 -- Time needed (in milliseconds): 15.7
Number of items: 256000 -- Time needed (in milliseconds): 34.4
铬:
built-in sort
Number of items: 1000 -- Time needed (in milliseconds): 2.7
Number of items: 2000 -- Time needed (in milliseconds): 1.6
Number of items: 4000 -- Time needed (in milliseconds): 1.6
Number of items: 8000 -- Time needed (in milliseconds): 3.3
Number of items: 16000 -- Time needed (in milliseconds): 6.1
Number of items: 32000 -- Time needed (in milliseconds): 10.7
Number of items: 64000 -- Time needed (in milliseconds): 24.6
Number of items: 128000 -- Time needed (in milliseconds): 53.8
Number of items: 256000 -- Time needed (in milliseconds): 158
heapsort
Number of items: 1000 -- Time needed (in milliseconds): 0.3
Number of items: 2000 -- Time needed (in milliseconds): 0.1
Number of items: 4000 -- Time needed (in milliseconds): 0.4
Number of items: 8000 -- Time needed (in milliseconds): 0.8
Number of items: 16000 -- Time needed (in milliseconds): 2
Number of items: 32000 -- Time needed (in milliseconds): 4.1
Number of items: 64000 -- Time needed (in milliseconds): 8.9
Number of items: 128000 -- Time needed (in milliseconds): 19.6
Number of items: 256000 -- Time needed (in milliseconds): 62.4
答案 0 :(得分:2)
免责声明:这不是一个完整的答案,但我认为值得发布。
我发现的一个问题是你认为要复制的元素便宜。如果我用String(Math.random())
替换随机调用,我会在Firefox中获得这些结果:
built-in sort
Number of items: 1000 -- Time needed (in milliseconds): 0.6
Number of items: 2000 -- Time needed (in milliseconds): 1.2
Number of items: 4000 -- Time needed (in milliseconds): 2.5
Number of items: 8000 -- Time needed (in milliseconds): 5.6
Number of items: 16000 -- Time needed (in milliseconds): 12.5
Number of items: 32000 -- Time needed (in milliseconds): 31.4
Number of items: 64000 -- Time needed (in milliseconds): 77.8
Number of items: 128000 -- Time needed (in milliseconds): 171.9
Number of items: 256000 -- Time needed (in milliseconds): 384.9
heapsort
Number of items: 1000 -- Time needed (in milliseconds): 1
Number of items: 2000 -- Time needed (in milliseconds): 1.6
Number of items: 4000 -- Time needed (in milliseconds): 3.4
Number of items: 8000 -- Time needed (in milliseconds): 7.3
Number of items: 16000 -- Time needed (in milliseconds): 16.2
Number of items: 32000 -- Time needed (in milliseconds): 42
Number of items: 64000 -- Time needed (in milliseconds): 116.4
Number of items: 128000 -- Time needed (in milliseconds): 465.7
Number of items: 256000 -- Time needed (in milliseconds): 757.6
你的heapsort在Chrome中仍然更快。我想用字符串做得更好(引用计数?必须检查)。
值得注意的是,即使情况如此,对阵列进行线性扫描以确定使用哪种算法也是有意义的。