web-dev-qa-db-fra.com

Récursion infinie dans le tri rapide JavaScript?

Voici le code quicksort que j'ai écrit. La fonction ne fonctionne pas car elle ne peut pas atteindre le cas de base. Si je connecte le pivot, r et l à la console, ils restent les mêmes quel que soit le nombre d'appels de la fonction de tri. Je me demande donc si les arguments l, r ne sont pas vraiment passés dans la fonction en tant que données. Pourquoi est-ce arrivé?

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));
    }
}
31
Yujun Wu

Je pense que le problème ici est que votre étape de partitionnement ne réduit pas nécessairement le tableau d'entrée. Par exemple, voyons ce qui se passe si vous essayez de trier [1, 2]. Dans ce cas, votre élément pivot sera l'élément 2. Puisque 1> 2 est faux, 1 est ajouté à la liste l. Puisque 2> 2 est faux, 2 est ajouté à la liste l. Par conséquent, votre appel récursif sur la liste l aura exactement les mêmes arguments que votre appel d'origine, provoquant une récursion infinie.

Pour résoudre ce problème, essayez de diviser l'entrée en trois listes: une de plus petites valeurs, une de valeurs égales et une de plus grandes valeurs. Ce code est affiché ici:

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

Cette nouvelle version regroupe explicitement les éléments égaux dans leur propre liste, ils ne sont donc pas triés récursivement par l'un ou l'autre des appels récursifs. Il gère également avec élégance les éléments en double.

J'espère que cela t'aides!

332
templatetypedef

Si vous choisissez la plus grande valeur du tableau comme élément pivot, toutes les valeurs de data se retrouveront dans le tableau l et aucune dans r. Ainsi, la récursivité ne s'arrêtera jamais (et gardera l, r et pivot aux mêmes valeurs). À moins qu'il ne s'agisse d'un exercice cérébral, l'utilisation de data.sort() devrait faire un meilleur travail. ;)

1

JavaScript passe les objets par référence (les tableaux sont aussi des objets). Si vous voulez les passer par valeur, vous devez utiliser la fonction d'épissage comme expliqué ici .

Notez que cela créera un grand nombre de copies de vos données. Vous voudrez probablement utiliser la fonction native sort ().

0
user1115652