2009-12-06 5 views
2

J'implémente ma propre liste chaînée en Java. La classe de noeud a simplement un champ de chaîne appelé "nom" et un noeud appelé "lien". En ce moment j'ai une classe de pilote de test qui insère seulement plusieurs noms séquentiellement. Maintenant, j'essaie d'écrire une méthode de tri pour classer les nœuds par ordre alphabétique, mais j'ai un peu de mal avec ça. J'ai trouvé ce pseudo-code d'une bulle de la part de quelqu'un d'autre et j'ai essayé de l'implémenter, mais il ne triait pas complètement les entrées. Je ne suis pas vraiment sûr pourquoi. Toutes les suggestions sont appréciées!Tri manuel d'une liste chaînée en Java (lexicalement)

private void sort() 
    { 
     //Enter loop only if there are elements in list 
     boolean swapped = (head != null); 

     // Only continue loop if a swap is made 
     while (swapped) 
     { 
      swapped = false; 

      // Maintain pointers 
      Node curr = head; 
      Node next = curr.link; 
      Node prev = null; 

      // Cannot swap last element with its next 
      while (next != null) 
      { 
       // swap if items in wrong order 
       if (curr.name.compareTo(next.name) < 0) 
       { 
        // notify loop to do one more pass 
        swapped = true; 

        // swap elements (swapping head in special case 
        if (curr == head) 
        { 
         head = next; 
         Node temp = next.link; 
         next.link = curr; 
         curr.link = temp; 
         curr = head; 
        } 
        else 
        { 
         prev.link = curr.link; 
         curr.link = next.link; 
         next.link = curr; 
         curr = next; 
        } 
       } 

       // move to next element 
       prev = curr; 
       curr = curr.link; 
       next = curr.link; 
      } 
     } 
    } 
+0

Pour ce que ça vaut, je pense que le '<' dans la comparaison rendrait votre sorte aller dans l'ordre DESCENDANT. –

+0

pouvez-vous donner un exemple de "ne pas trier entièrement les entrées"? - votre code de bubbleort semble OK –

Répondre

3

J'ai passé quelques minutes à regarder votre code à la recherche d'erreurs mais n'en ai trouvé aucune.

Je dirais jusqu'à ce que quelqu'un de plus intelligent ou de plus dur travail arrive, vous devriez essayer de déboguer cela par vous-même. Si vous avez un EDI comme Eclipse, vous pouvez faire un seul pas dans le code tout en regardant les valeurs des variables; Sinon, vous pouvez insérer des instructions d'impression dans quelques endroits et vérifiez ce que vous voyez avec ce que vous attendiez.


MISE À JOUR Je

Je copiais votre code et testé. Mis à part le fait qu'il trie par ordre décroissant (ce qui n'est peut-être pas ce que vous vouliez), il a parfaitement fonctionné pour un échantillon de 0, 1 et 10 nœuds aléatoires. Alors, où est le problème?

MISE A JOUR II

deviner encore ce qu'on pourrait entendre par « il ne sort pas complètement les entrées. » Il est possible que vous attendiez un tri lexicographique (c'est-à-dire 'a' avant 'B'), et cela ne sort pas comme prévu pour les mots mixtes majuscules/minuscules. La solution dans ce cas est d'utiliser la méthode StringcompareToIgnoreCase(String str).

+0

"compareToIgnoreCase (String str)" C'est exactement la solution à mon problème. Malheureusement, je ne faisais pas attention à ce que certaines de mes données de test étaient mélangées en majuscules et minuscules ... Je ne peux pas croire que j'ai négligé quelque chose d'aussi simple. Aussi, j'ai changé la comparaison en "> 0" pour mettre en ordre croissant, merci! – Aaron

+1

Oh bien, ma persévérance a été payante. Oh, attends, ce n'est pas le cas: pas d'acceptation, pas d'upvote. Pas de fleurs non plus, et je parie que tu ne m'appelleras même pas!* sniff * –

+1

Hé, oublie d'accepter ... Je n'ai pas de fleurs, mais j'ai récemment hérité de beaucoup de bonbons: 3 – Aaron

0

Ceci peut ne pas être la solution que vous cherchez, mais c'est simple et agréable. Peut-être que vous êtes paresseux comme je suis.

Étant donné que vos nœuds ne contiennent qu'un seul élément de données, vous n'avez pas vraiment besoin de remanier à nouveau vos nœuds; vous pouvez simplement échanger les valeurs sur les nœuds tout en laissant la structure de la liste elle-même intacte. De cette façon, vous êtes libre d'implémenter Bubble Sort tout simplement.

+0

Oui, ce serait probablement la façon la plus simple de le faire, même si je suppose que pour ma propre satisfaction, j'aimerais savoir comment utiliser les nœuds eux-mêmes. – Aaron

0

Vous devez utiliser les procédures de tri fournies par le langage.

try this tutorial.

Fondamentalement, vous avez besoin de votre classe d'éléments pour mettre en œuvre java.lang.Comparable, dans lequel vous simplement déléguer à obj.name.compareTo(other.name)

vous pouvez utiliser Collections.sort(yourCollection)

vous pouvez également créer un java.util.Comparator qui sait comment comparer vos objets

+3

Citation: "J'applique ma propre liste chaînée en Java." C'est un exercice d'apprentissage qui ne serait pas réalisé en utilisant les APIs en boîte. –

+0

la question ne dit pas que c'est un exercice d'apprentissage ou que les api «en boîte» ne devraient pas être utilisés. c'est votre interprétation. – pstanton

+1

mon interprétation est que c'est aussi un exercice d'apprentissage. Sinon, il n'aurait pas besoin d'implémenter une liste chaînée. –

0

Pour obtenir de bonnes performances, vous pouvez utiliser Merge Sort. Sa complexité temporelle est O (n * log (n)) et peut être implémentée sans surcharge de mémoire pour les listes.

Le tri par bulles n'est pas une bonne méthode de tri. Vous pouvez lire le What is a bubble sort good for? pour plus de détails.

+0

Oui, il y a certainement de meilleurs tris là-bas que le tri des bulles, mais je pense qu'avoir O (n^2) pour l'exécution n'est pas si mauvais pour le petite entrée je la teste avec (~ 50 entrées). De plus, le tri est effectué «en place» et je n'ai donc pas besoin d'allouer plus d'espace lors d'un processus de «fusion». Peut-être plus tard, je vais mettre en œuvre un algorithme de tri rapide, merci pour la suggestion. – Aaron

+0

@Aaron Si vous avez seulement 50 objets, le tri par bulles est correct, ce serait bien si vous mettez à jour la question. En ce qui concerne l'allocation, je voudrais attirer votre attention sur le fait que pour une bonne implémentation du tri par fusion sur _lists_, aucune allocation supplémentaire n'est requise. (En revanche, dans le cas de tableaux, des allocations sont nécessaires). – sergtk

0

Cela peut être un peu trop tard. Je construirais la liste en insérant tout pour commencer car trier une liste chaînée n'est pas amusant.

Je suis sûr que votre professeur ou professeur ne veut pas que vous utilisiez la bibliothèque native de java. Cependant, cela étant dit, il n'y a pas de moyen vraiment rapide de recourir à cette liste.

Vous pouvez lire tous les nœuds dans l'ordre dans lequel ils se trouvent et les stocker dans un tableau. Triez le tableau, puis reconnectez les noeuds. Je pense que la complexité Big-Oh de ce serait O (n^2) donc en réalité une sorte de bulle avec une liste liée est suffisante

+0

Merci pour les pensées. Je le fais comme un exercice dans les structures de données, donc je voulais éviter toute utilisation de tableaux supplémentaires et coller juste à la liste elle-même. J'avais d'abord essayé de mettre les choses en ordre sur la fonction d'insertion, mais je trouvais difficile de parcourir la liste tout en changeant la liste. Par exemple, voici à quoi ressemblait mon itération: Node temp = head; ! while (temp = null; // faire quelque chose ici temp = temp.link;} je pourrais trouver un « indice » de l'endroit où insérer le nœud, mais pour autant que l'application des modifications au nœud de tête lui-même, je ne pouvais pas le comprendre :( – Aaron

0

J'ai fait un tri de fusion sur la liste des liens simples et ci-dessous est le code.

public class SortLinkedList { 

public static Node sortLinkedList(Node node) { 

    if (node == null || node.next == null) { 
     return node; 
    } 
    Node fast = node; 
    Node mid = node; 
    Node midPrev = node; 
    while (fast != null && fast.next != null) { 
     fast = fast.next.next; 
     midPrev = mid; 
     mid = mid.next; 
    } 
    midPrev.next = null; 
    Node node1 = sortLinkedList(node); 
    Node node2 = sortLinkedList(mid); 
    Node result = mergeTwoSortedLinkedLists(node1, node2); 
    return result; 
} 

public static Node mergeTwoSortedLinkedLists(Node node1, Node node2) { 
    if (null == node1 && node2 != null) { 
     return node2; 
    } else if (null == node2 && node1 != null) { 
     return node1; 
    } else if (null == node1 && null == node2) { 
     return null; 
    } else { 

     Node result = node1.data <= node2.data ? node1 : node2; 
     Node prev1 = null; 
     while (node1 != null && node2 != null) { 
      if (node1.data <= node2.data) { 
       prev1 = node1; 
       node1 = node1.next; 
      } else { 
       Node next2 = node2.next; 
       node2.next = node1; 
       if (prev1 != null) { 
        prev1.next = node2; 
       } 
       node1 = node2; 
       node2 = next2; 
      } 
     } 
     if (node1 == null && node2 != null) { 
      prev1.next = node2; 
     } 
     return result; 
    } 
} 

public static void traverseNode(Node node) { 
    while (node != null) { 
     System.out.print(node + " "); 
     node = node.next; 
    } 
    System.out.println(); 

} 

public static void main(String[] args) { 
    MyLinkedList ll1 = new MyLinkedList(); 

    ll1.insertAtEnd(10); 
    ll1.insertAtEnd(2); 
    ll1.insertAtEnd(20); 
    ll1.insertAtEnd(4); 
    ll1.insertAtEnd(9); 
    ll1.insertAtEnd(7); 
    ll1.insertAtEnd(15); 
    ll1.insertAtEnd(-3); 
    System.out.print("list: "); 
    ll1.traverse(); 
    System.out.println(); 
    traverseNode(sortLinkedList(ll1.start)); 

} 

}

La classe Node:

public class Node { 
int data; 
Node next; 

public Node() { 
    data = 0; 
    next = null; 
} 

public Node(int data) { 
    this.data = data; 
} 

public int getData() { 
    return this.data; 
} 

public Node getNext() { 
    return this.next; 
} 

public void setData(int data) { 
    this.data = data; 
} 

public void setNext(Node next) { 
    this.next = next; 
} 

@Override 
public String toString() { 
    return "[ " + data + " ]"; 
} 

}

La classe MyLinkedList:

public class MyLinkedList { 
Node start; 

public void insertAtEnd(int data) { 
    Node newNode = new Node(data); 
    if (start == null) { 
     start = newNode; 
     return; 
    } 
    Node traverse = start; 
    while (traverse.getNext() != null) { 
     traverse = traverse.getNext(); 
    } 
    traverse.setNext(newNode); 
} 

public void traverse() { 
    if (start == null) 
     System.out.println("List is empty"); 
    else { 
     Node tempNode = start; 
     do { 
      System.out.print(tempNode.getData() + " "); 
      tempNode = tempNode.getNext(); 
     } while (tempNode != null); 
     System.out.println(); 
    } 
} 

}