2012-04-01 16 views
4

次のQuicksort実装の契約を変更して、ソート操作を実行するのに必要な再帰呼び出しの数を戻したいと考えています。関数を完全に再実装せずに再帰関数契約を変更しますか?

出典:http://rosettacode.org/wiki/Sorting_algorithms/Quicksort#Clojure

(defn qsort [[pivot & xs]] 
    (when pivot 
    (let [smaller #(< % pivot)] 
     (lazy-cat (qsort (filter smaller xs)) 
       [pivot] 
     (qsort (remove smaller xs)))))) 

私が何をしたいのですが、何が内部で上記のqsort実装を使用counted-qsortを実装しています。

私はこれを行う方法の例を探しています。私は(bind ...)が関与している可能性があると思います。私はしばらくの間、この質問をいじって、ここに私が思い付いたものです

答えて

5

:それは数のカウントを保持している原子を管理できるように

(defn counted-qsort [coll] 
    (let [count (atom 0) qs qsort] 
    (with-redefs [qsort (fn [coll] 
          (swap! count inc) 
          (prn coll) 
          (qs coll))] 
     (dorun (qsort coll))) 
    (deref count))) 

この機能を一時的にはqsortを再定義します最終的にはqsortが呼び出されます。 letバインディング内のqsは、元のqsort関数を無限再帰を避けるために再定義されたバージョンで参照できるようにします。

「深さ」が正しい用語ではないことがわかっているため、「深さ」の代わりに「カウント」を使用しました。この関数は、qsortが呼び出された回数をカウントします。「ツリー」の深さではありません。

この方法で怠惰を保存できるかどうかわかりません。デバッグ用prn

出力例:

[1 2 3] 
() 
(2 3) 
() 
(3) 
() 
() 
7 ;return value 

私はClojureの1.3と仮定し、qsortがすでに同じ名前空間で定義されています。