2013-02-07 21 views
31

ここには私が書いたquicksortコードです。ベースケースに届かないため機能しません。ピボットをrlにコンソールに記録すると、ソート関数が何回呼び出されても同じままです。したがって、引数l,rが本当にデータとして関数に渡されないのだろうかと思います。なぜそれが起こったのですか?JavaScriptクイックソートの無限再帰?

function sort(data){ 
    if(data.length < 2){ 
     return data; 
    } 
    else{ 
     var l = []; 
     var r = []; 
     var pivot = parseInt(data.length/2); 
     for(i=0; i<data.length; i++){ 
      if(data[i] > data[pivot]){ 
       r.push(data[i]); 
      } 
      else{ 
       l.push(data[i]); 
      } 
     } 
     return sort(l).concat(sort(r)); 
    } 
} 
+3

各再帰呼び出しのlとrを上書きしています。ソート機能の外でそれらを初期化する必要があります。 – marteljn

+0

@marteljnはい。しかし、返す前にconsole.log(l)を置くと、同じ配列が出力されます。私は混乱しています –

+2

「originalArray.sort()」を呼び出すだけで何が問題なのですか? –

答えて

327

ここでの問題は、パーティショニングのステップが必ずしも入力配列を縮小しないということです。たとえば、[1、2]をソートしようとするとどうなるかをトレースしましょう。この場合、ピボット要素は要素2になります.1> 2が偽であるため、1がリストlに追加されます。 2> 2が偽であるので、2がリストlに追加されます。その結果、リストlの再帰呼び出しは、元の呼び出しとまったく同じ引数を持ち、無限再帰を引き起こします。

この問題を解決するには、小さい値、等しい値、大きい値の3つのリストに入力を分割してみてください。この新しいバージョンを明示的グループ、自分のリストに等しい要素が

function sort(data){ 
    if (data.length < 2){ 
    return data; 
    } else { 
    var l = []; 
    var r = []; 
    var e = []; 
    var i = 0; 
    var pivot = (data.length/2) | 0; 

    for(i = 0; i < data.length; i++) { 
     if (data[i] > data[pivot]) { 
     r.push(data[i]); 
     } else if (data[i] < data[pivot]) { 
     l.push(data[i]); 
     } else { 
     e.push(data[i]); 
     } 
    } 
    return sort(l).concat(e, sort(r)); 
    } 
} 

ので、それらを再帰的に再帰呼び出しのどちらかによってソートされていません。このコードは、ここで示されています。重複した要素も正常に処理します。

希望すると便利です。

+1

+1。ちょっとした改良: 'sort(l).concat(e、sort(r));' – Bergi

+1

@ Bergi-ありがとう!私は決してJSプログラマーではなく、あなたがそれを行うことができるか分からなかった。 – templatetypedef

+6

gg Randall。 'sort'タグに対するAPIアクセス呼び出しに関するいくつかの統計情報を取得しましょう。 :) –

0

JavaScriptはオブジェクトを参照渡しします(配列もオブジェクトです)。値渡しの場合は、hereのようにスプライス関数を使用する必要があります。

これにより、データのコピーが多数作成されることに注意してください。おそらくネイティブのsort()関数を使いたいと思うでしょう。

+1

ここでは問題はないと思います。無限再帰は、参照渡しのためではなく、元のコードが処理する必要があるケースの1つを正しく処理しないという事実のためです。 – templatetypedef

+0

あなたの質問は無限回帰について何も言及していません。 – nus

1

配列の最大値をピボット要素として選択すると、dataのすべての値は配列lになり、いずれもrになりません。したがって、再帰は決して止まらなくなります(lrおよびpivotを同じ値に保ちます)。 これが脳の訓練でない限り、data.sort()を使用するとより良い仕事をするはずです。 ;)