我正在做一个手动创建排序算法的项目。
经过多次测试后我发现我的heapsort比quicksort更快(我认为应该是另一种方式),我的选择排序也比插入排序快。有谁知道这里的问题是什么?
我正在测试使用从-100到100的整数,随机生成,数组中的5000个值(我修改了这个数字几次,仍然是相同的问题)。 我的快速排序不到位。 我想也许flash的递归函数很慢?我的heapsort使用循环,不像quicksort。这只是一个假设。
这是我的代码,如果他们有帮助的话。我启动一个计时器,运行类的exec()函数,停止计时器并计算经过的时间。代码来自维基百科。 heapsort vs quicksort的问题:
public class Quick {
public static function exec(seq:Vector.<int>):Vector.<int> {
if (seq.length<=1) {
return seq;
}
var smallPart:Vector.<int>=new Vector.<int>
var bigPart:Vector.<int>=new Vector.<int>
var n:int=seq.length;
var pivotPosition:int=Math.floor(Math.random()*n);
var pivot:int=seq.splice(pivotPosition,1)[0];
for (var i:int=0; i<n-1; i++) {
if (seq[i]<=pivot) {
smallPart.push(seq[i]);
} else {
bigPart.push(seq[i]);
}
}
seq=exec(smallPart).concat(exec(bigPart),Vector.<int>([pivot]));
return seq;
}
}
public class Heap{
public static function exec(seq:Vector.<int>) {
var n:int=seq.length;
heapify(seq);
var end:int=n-1;
while (end > 0) {
var temp:int=seq[end];
seq[end]=seq[0];
seq[0]=temp;
siftDown(seq, 0, end-1);
end--;
}
return seq
}
public static function heapify(seq:Vector.<int>) {
var n:int=seq.length
var start:int=n/2-1
while (start >= 0) {
siftDown(seq, start, n-1);
start--;
}
}
public static function siftDown(seq:Vector.<int>, start:int, end:int) {
var root:int=start;
while (root * 2 + 1 <= end) {
var child:int=root*2+1;
var swap:int=root;
if (seq[swap]<seq[child]) {
swap=child;
}
if (child+1<=end&&seq[swap]<seq[child+1]) {
swap=child+1;
}
if (swap!=root) {
var temp:int=seq[root];
seq[root]=seq[swap];
seq[swap]=temp;
root=swap;
} else {
break;
}
}
}
}
插入排序与选择排序的问题:
public class Insertion{
public static function exec(seq:Vector.<int>) {
var n:int=seq.length;
for (var i:int=1; i<n; i++) {
var holder:int=seq[i];
var j:int=i-1;
while (seq[j]>holder) {
seq[j+1]=seq[j];
j-=1;
if (j<0) {
break
}
}
seq[j+1]=holder;
}
return seq
}
}
public class Selection{
public static function exec(seq:Vector.<int>):void{
var currentMinimum:int;
var n:int=seq.length;
for (var i:int = 0; i < n-1; i++) {
currentMinimum=i;
for (var j:int = i+1; j < n; j++) {
if (seq[j]<seq[currentMinimum]) {
currentMinimum=j;
}
}
if (currentMinimum!=i) {
var temp:int=seq[i];
seq[i]=seq[currentMinimum];
seq[currentMinimum]=temp;
}
}
}
}
答案 0 :(得分:3)
好的,所以我实际上并不知道动作脚本,但有很多可能性:
语言问题
我不知道actionscript是如何工作的,但是在C ++和其他可能的语言中,如果你通过值而不是引用传递向量,它可以显着减慢速度。(感谢alxx清除它向上)
在quicksort案例中,您似乎正在创建许多新的向量。如果这个操作很慢(我再次提醒你,我不知道动作脚本)它可能会偏向于支持heapsort。
正如The_asMan所说,也许你的计时方法不准确,也许你应该使用不同的语言功能。
算法问题
您正在使用[-100,100]中的5000个值。这意味着将会有大量的重复。快速排序快速的主要原因之一是您可以使用批次优化。如果存在重复值,则普通(无优化)快速排序可能会非常慢。
此外,还有许多其他优化方法可以使快速排序在实践中更快。
感知问题
嘿。感知问题。 Trololol;)
插入排序不一定比选择排序更快(我不确定从哪里得到这个想法)。插入排序非常快的主要情况是列表几乎已排序。在这种情况下,每个元素的插入只需要几次交换。但是在一般情况下(随机数字)它没有比选择排序有显着优势。
希望这有帮助。
答案 1 :(得分:0)
如果要比较那些排序算法的速度。 那你为什么不预先创建一个随机的Vector / Array。然后测试它的速度。 喜欢:
var source:Vector = new Vector().<5000, true>;
genRandomNumber(source);
var t:int = getTimer();
quicksort(source ....);
t = getTimer() - t;
trace("quicksort:" + t + "ms");
genRandomNumber(source);
t = getTimer();
heapsort(source ...);
t = getTimer() - t;
trace("heapsort:" + t + "ms");
.
.
.
这是kirupa的quicksort演示。我之前测试过一些排序算法,而quicksort是最快的。
答案 2 :(得分:0)
我认为要真正回答这个问题,你需要退后一步,检查你的假设。当你说“heapsort应该比quicksort更快”时,是什么让你这么说?
如果你的理由是“因为有一个更好的大O符号”,你需要回顾一下大O的真正含义。 big O表示法忽略了常数因子,当使用5000这样的小数时,常数因子可以压倒渐近行为。
如果您的理由是“因为维基百科说通常会更快”,那么您需要关注“通常”。许多因素可以影响哪一个更快,例如您的样本量有多大,数字是否已经部分排序,您有多少重复数字。其他因素包括缓存行为 - 某些算法涉及更多本地化的内存访问,并且可以更好地利用缓存。另一方面,与已编译的程序相比,解释性语言可能会或可能不会搞砸那个地方,从而进一步混淆了问题。
你应该尝试的一件事是运行一些不同的测试数据 - 尝试1000万件物品,其中的物品数量从0到40亿左右。然后尝试10个项目,从0到20不等。对于这两种情况,您不一定希望看到相同的算法“获胜”。
您现在使用的测试数据可能不是通用排序算法的最佳用例。如果从仅200个潜在池中选择5000个数字,则可以保证有大量重复数据。如此多的重复数据,计数排序几乎肯定是最快的。
需要考虑的其他事项 - 您对计时功能有多大信心?你知道如果解释或编译动作脚本吗?您是否正在运行测试100次左右,以便进行任何需要完成的初始化工作?