在數學,我創建單鏈表,像這樣:數學「鏈表」和性能
toLinkedList[x_List] := Fold[pair[#2, #1] &, pair[], Reverse[x]];
fromLinkedList[ll_pair] := List @@ Flatten[ll];
emptyQ[pair[]] := True;
emptyQ[_pair] := False;
使用符號pair
的利弊細胞具有Flatten
安全工作,即使列表包含Mathematica-優勢style List
s,並且允許您使用MakeExpression
/MakeBoxes
來定義自定義符號,這使得一切都變得更加愉快。爲了避免與$IterationLimit
混淆,我編寫了使用While
循環或NestWhile
而不是遞歸使用這些列表的函數。當然,我想看看哪種方法會更快,所以我寫了兩個候選人,所以我能看到「時間打:
nestLength[ll_pair] :=
With[{step = {#[[1, -1]], #[[-1]] + 1} &},
[email protected][step, {ll, 0}, ! [email protected]@# &]];
whileLength[ll_pair] :=
Module[{result = 0, current = ll},
While[! [email protected],
current = current[[2]];
++result];
result];
結果非常奇怪。我測試了長度爲10000的鏈表上的函數,並且whileLength
通常快了大約50%,在大約0.035秒到nestLength
的0.055秒處。但是,偶爾whileLength
需要約4秒。我認爲可能存在一些緩存行爲,所以我開始生成新的隨機列表來檢查,並且whileLength
在第一次運行時不一定會很慢,並且具有新的列表;它可能需要幾十次才能看到放緩,但不會再發生(至少不是我試圖用每個列表進行的200次)。
可能會發生什麼?
僅供參考,我用於測試的功能是這樣的:
getTimes[f_, n_] :=
With[{ll = [email protected][100, 10000]},
Table[Timing[[email protected]], {n}][[All, 1]]]
編輯:我忘了前面提到的版本;我得到這些結果與數學8.
編輯第二:當我讀到Daniel Lichtblau's answer,我意識到,我的時間「典型」運行省略了領先的0它已經固定。
編輯第三個:我認爲Leonid Shifrin是正確的關聯問題與Module
;我可以用Module
更換With
得到相同的排序從NestWhile
基於版本的行爲:
nestModuleLength[ll_pair] :=
Module[{step = {#[[1, -1]], #[[-1]] + 1} &},
[email protected][step, {ll, 0}, ! [email protected]@# &]];
In[15]:= Select[getTimes[nestModuleLength, 100], # > 3 &]
Out[15]= {3.797}
Developer'PackedArrayQ可能是相關 – 2011-02-23 20:36:13
@Yaroslav Bulatov:我不明白爲什麼包裝陣列將是相關的,因爲沒有應裝除非'RandomInteger生成的初始'List' ',它立即轉換成樹狀表達式。 – Pillsy 2011-02-23 20:52:57
您使用的是版本7還是版本8?無論如何,對於它的價值,我認爲你已經發現了一些錯誤,或者至少是評估行爲中的一個弱點。 – 2011-02-24 02:28:56