2011-09-22 26 views
2

我正在做一個項目,我手動創建排序算法。自定義排序算法的速度問題

經過多次測試,我發現我的堆排序比快速排序快(我認爲它應該是另一種方式),我的選擇排序也比插入排序更快。有人知道這裏有什麼問題嗎?我正在測試使用整數從-100到100,隨機生成,在數組中的5000個值(我修改了這個數字,幾次,仍然是同樣的問題)。 我的快速排序不在位。 我認爲也許flash的遞歸函數很慢?我的heapsort使用循環,不像quicksort。這只是一個假設。

這裏是我的代碼,如果他們幫助。我啓動一個計時器,運行該類的exec()函數,停止計時器並計算經過的時間。代碼來自維基百科。 問題堆排序VS快速排序:

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; 
     }  
    } 
} 

}

問題插入排序VS選擇排序:

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; 
     } 
    } 
} 

}

+2

不要使用定時器,使用日期。我記得在某個地方聽到計時器可能會在錯誤的時間發生。 –

回答

3

好了,所以我真的不知道動作但也有這麼多的可能性:

語言問題

我不知道該如何動作的作品,但在C++和潛在的其他語言,如果你通過值而不是引用來傳遞向量,它會顯着減慢速度。(感謝alxx的清除)

在快速排序的情況下,你似乎創造了很多新的載體。如果這個操作很慢(我再次提醒你,我不知道動作),它可能偏向於傾向於堆排序。

正如The_asMan所說,或許你的計時方法不準確,也許你應該使用不同的語言功能。

算法問題

您正在使用從[-100,100] 5000個值。這意味着將會有大量的重複。 quicksort的主要原因之一是速度很快,因爲您可以使用優化的lot。如果存在重複值,則平滑(無優化)快速排序可能會非常緩慢。

另外還有許多其他的優化使得在實踐中快速排序通常更快。

感知問題

嘿。感知問題。Trololol;)

插入排序不一定比選擇排序(我不知道你在哪裏得到了這個想法)更快。其中,插入排序是主要情況非常快是當列表幾乎排序。在這種情況下,插入每個元素只需要幾次交換。但在一般情況下(隨機數字),它沒有比選擇排序顯着的優勢。

希望這會有所幫助。

+1

Vector是一個類,總是通過引用傳遞給ActionScript。 – alxx

0

如果要比較的那些排序算法的速度。 那麼爲什麼不預先創建一個隨機的矢量/數組。然後測試它的速度。 像:

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"); 
. 
. 
. 

這裏有一個quicksort演示通過kirupa。我之前測試過一些排序算法,並且quicksort是最快的。

0

我認爲,要真正回答這個問題,你需要退後一步,並檢查你的假設。當你說「像heapsort應該比quicksort快」時,是什麼讓你這麼說?

如果你的原因是「因爲人們有更好的大O符號」,你需要回顧一下大O字的真正含義。大O符號忽略了不變的因素,當使用5000這樣的小數字時,常數因子可能壓倒漸近行爲。

如果你的理由是「因爲維基百科說通常速度更快」,你需要關注「通常」。許多因素可以影響哪一個更快,例如樣本量有多大,數字是否已經部分排序,您擁有多少重複數字。其他因素包括緩存行爲 - 一些算法涉及更多本地化的內存訪問,並且可以更好地利用緩存。另一方面,與編譯的程序相比,解釋型語言可能會或可能不會搞砸那個地方,從而進一步混淆事物。

你應該肯定嘗試的一件事是運行一些不同的測試數據 - 嘗試1000萬個項目,其中項目數量從0到40億左右。然後嘗試10個項目,從0到20不等。您不一定期望在這兩種情況下看到相同的算法「贏」。

您現在使用的測試數據可能不是通用排序算法的最佳用例。如果從200個潛在資源池中選擇5000個號碼,則可以保證有大量重複資料。有這麼多的重複,計數排序幾乎肯定是最快的。

需要考慮的其他事項 - 您對定時功能的自信程度如何?你知道動作是解釋還是編譯?你是否正在運行你的測試100次左右來對所有需要完成的初始化工作進行amoritize?