首先,當列表非常隨機時,排序不起作用,例如, f [2,3,4,1,2,4,6,0,6,7]
其次,要回答你的問題,以這種特殊的功能是如何工作的, 你可以用以下print
添加到您的代碼很容易想象它:
fun f ([x]) = [x]
| f(x :: ls) = (print((Int.toString (x))^"\n");
let
val (y :: ys) = f ls
val x_str = Int.toString (x)
val y_str = Int.toString (y)
val ys_str = concat (map Int.toString ys);
val y_gt_x = if y > x then " ---> this one applies " else ""
val x_gt_y = if x >= y then " ---> this one applies " else ""
in
(print ("if "^y_str^" > "^x_str^
"\n then "^x_str^" :: "^y_str^ys_str^y_gt_x^
"\n else "^y_str^" :: "^x_str^ys_str^x_gt_y^"\n");
if y > x then x :: y :: ys
else
y :: x :: ys)
end)
這對於對上述無序列表輸出以下內容:
- f [2,3,4,1,2,4,6,0,6,7];
2
3
4
1
2
4
6
0
6
if 7 > 6
then 6 :: 7 ---> this one applies
else 7 :: 6
if 6 > 0
then 0 :: 67 ---> this one applies
else 6 :: 07
if 0 > 6
then 6 :: 067
else 0 :: 667 ---> this one applies
if 0 > 4
then 4 :: 0667
else 0 :: 4667 ---> this one applies
if 0 > 2
then 2 :: 04667
else 0 :: 24667 ---> this one applies
if 0 > 1
then 1 :: 024667
else 0 :: 124667 ---> this one applies
if 0 > 4
then 4 :: 0124667
else 0 :: 4124667 ---> this one applies
if 0 > 3
then 3 :: 04124667
else 0 :: 34124667 ---> this one applies
if 0 > 2
then 2 :: 034124667
else 0 :: 234124667 ---> this one applies
val it = [0,2,3,4,1,2,4,6,6,7] : int list
-
正如你所看到的,功能f
遞歸調用自身在let
綁定區段。 (檢查代碼: let val (y :: ys) = f ls
,你可以看到,f ls
是函數f
的遞歸調用,所以你的y :: ys
分析作爲in
體內的遞歸調用是不正確的,這僅僅是在前面加上的操作元素y
至列表ys
)
in
主體不會被評估,除非一直列在列表的末尾。因此,in
正文將首先評估列表的最後兩個元素,例如7 > 6
並相應地增加列表ys
。
第三,回答點數一個,爲什麼排序功能f
不能正常工作,是因爲它不斷加入新的元素,ys
如果沒有新的元素放入順序ys
相對於其餘看到元素。是的,列表ys
的第一個元素與要添加的新元素進行比較,因此兩個中最大的元素將首先添加到ys
的剩餘部分,但這不能保證關於第二個元素的正確放置第三等元素ys
。
感謝您花時間設置和解釋!所以我很清楚1)遞歸調用然後首先運行首先將列表拆分爲用於比較的元素? 2)那麼隨着它的增長,ys就是新的列表了嗎? – cpd1
或多或少,更確切地說:遞歸調用將列表中的每個元素解除綁定到堆中並接近列表末尾,堆被回溯並且每個單獨的元素相應地被挖掘並進行比較,然後將這些元素插入到ys中。我建議你使用我提供的簡單輸入和更復雜輸入的代碼來玩,並理解爲什麼只輸出第一個數字,然後只進行比較。 –
我會感謝。這非常有用,所以非常感謝您爲我整理這些內容。我一直在努力瞭解這是如何工作的,但這應該有所幫助 – cpd1