Comment supprimer une valeur spécifique d'une liste liée java?
J'ai essayé de le faire dans mon implémentation, mais ce n'était pas facile.
Voici ce que j'essaye de faire:
a b c a b d b abba a z a Remove some of elements. a b d b abba a z a
Ce sont les pré- setup:
public static void main(String[] args) { LinkedQueue<String> q = new LinkedQueue<String>(); q.enqueue("a"); q.enqueue("b"); q.enqueue("c"); q.enqueue("a"); q.enqueue("b"); q.enqueue("d"); q.enqueue("b"); q.enqueue("abba"); q.enqueue("a"); q.enqueue("z"); q.enqueue("a"); System.out.println(q); System.out.println("Remove some of elements."); q.remove("a"); q.remove("f"); q.remove("c"); System.out.println(q); } }
Et la fonction principale:
public class LinkedQueue<Item> implements Iterable<Item> { private int N; // number of elements on queue private Node first; // beginning of queue private Node last; // end of queue // helper linked list class private class Node { private Item item; private Node next; } /** * Initializes an empty queue. */ public LinkedQueue() { first = null; last = null; N = 0; assert check(); } public Item dequeue() { if (isEmpty()) throw new NoSuchElementException("Queue underflow"); Item item = first.item; first = first.next; N--; if (isEmpty()) last = null; // to avoid loitering assert check(); return item; }
Et j'ai un résultat comme celui-ci. Cela ne change pas du tout ..
//How to do this...;<.. int remove(Item item) { Node cur = first.next; Node prev = first; while (cur !=null) { if (cur.item.equals(item)) { item = dequeue(); } cur = cur.next; // TODO } return 0; }
Il efface uniquement la valeur c
. Je ne sais pas pourquoi.
4 Réponses :
Dans votre instruction if, vous vérifiez si le cur
Node
est égal à Item
passé: if (cur. est égal à (élément))
.
Je pense que vous devriez vérifier si l ' Item
stocké dans le cur
Node
est égal à l' Item
passé dans votre fonction: if (cur.item.equals (item))
.
prev.next = cur.next;
ne me semble pas non plus avoir beaucoup de sens. prev est toujours le dernier
dans la boucle while
J'ai changé le problème.
En ce qui concerne les détails de la question, je suppose que vous êtes assez nouveau en Java. Ce que vous demandez et les détails que vous montrez sont totalement différents.
LinkedQueue
n'est applicable que si LinkedQueue est une classe genre et non un impl spécifique pour la classe de type Item. c'est-à-dire que vous ne créez pas d'objet de la classe LinkedQueue
. LinkedQueue
est différent.
cur.equals (item)
manque de connaissance du contrat égal et différence de == vs égal
. c'est-à-dire que vous comparez deux objets totalement différents. L'un est un Node et l'autre est un objet de classe Item.
Suggestion: notions de base claires, lire le livre de cathy Sierra.Scjp Sun Certified Programmer pour Java 6
En ce qui concerne la réponse, vous n'appelez littéralement pas remove from main (testez-le via un print instruction dans la méthode remove). C'est pourquoi vous obtenez toujours la même réponse.
Remarque: vous ne pouvez vraiment pas digérer la vraie solution même si nous le disons.
L'extrait de code suivant contient diverses méthodes remove ()
, tirées de l'une de mes implémentations LinkedList
, écrites en Java
.
Code
LinkedList.java (partly)
Steps: * loop to target node, * for each step, record: * previous node, * this node, * get next node, of target node, * get value of target node, as return value later, * if target is end, * if also head, head = null; * if not head, preNode.next = null; * end = preNode; * if targe is not end, replace it with its next node, logic: * node.value = nextNode.value; * node.next = nextNode.next; * return previously tracked value of target node,
LinkedListTest. java (en partie)
(test unitaire, via TestNG
)
import org.testng.Assert; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; /** * LinkedList test. * * @author eric * @date 1/28/19 6:03 PM */ public class LinkedListTest { private int n = 10; private LinkedList<Integer> llist; // linked list, private LinkedList<Integer> dupEvenLlist; // linked list, with duplicated even values, @BeforeMethod public void init() { // init llist, llist = new LinkedList(); // create linked list, Assert.assertTrue(llist.isEmpty()); LinkedList.appendRangeNum(llist, 0, n); // append range, // init dupEvenLlist, dupEvenLlist = new LinkedList(); // create linked list, LinkedList.appendRangeNum(dupEvenLlist, 0, n); // append range, LinkedList.appendRangeNum(dupEvenLlist, 0, n, 2); // append range, again, with step as 2 (only even numbers), Assert.assertEquals(dupEvenLlist.size(), n + n / 2); } // non-remove related test cases ... are deleted, // remove(k) - remove by index, @Test public void testRemoveByIndex() { for (int i = 0; i < n; i++) { Assert.assertEquals(llist.removeEnd().intValue(), n - 1 - i); // remove by end, in turn it remove by index, Assert.assertEquals(llist.size(), n - 1 - i); } Assert.assertTrue(llist.isEmpty()); } // remove(v) - remove by value, @Test public void testRemoveByValue() { Assert.assertFalse(llist.removeValue(n)); // not exists, for (int i = n - 1; i >= 0; i--) { Assert.assertTrue(llist.removeValue(i)); // remove by value, Assert.assertEquals(llist.size(), i); } Assert.assertTrue(llist.isEmpty()); Assert.assertFalse(llist.removeValue(0)); // empty, // remove from list with duplicated value, for (int i = 0; i < n; i++) { Assert.assertTrue(dupEvenLlist.removeValue(i)); } Assert.assertFalse(dupEvenLlist.isEmpty()); Assert.assertEquals(dupEvenLlist.size(), n / 2); } // removeAll(v) - remove all occurrences by value, @Test public void testRemoveAllByValue() { Assert.assertEquals(dupEvenLlist.removeAllValue(n), 0); // not exists, int remainSize = dupEvenLlist.size(); for (int i = 0; i < n; i++) { int rc = dupEvenLlist.removeAllValue(i); // remove all by value, Assert.assertEquals(rc, i % 2 == 0 ? 2 : 1); remainSize -= rc; Assert.assertEquals(dupEvenLlist.size(), remainSize); } Assert.assertTrue(dupEvenLlist.isEmpty()); Assert.assertEquals(dupEvenLlist.removeAllValue(0), 0); // empty, } }
Tous les cas de test réussiraient.
Explication
Méthodes:
T remove (int k)
, supprimer par index. private int size; // node count, private LinkedListNode<T> head; // first node, private LinkedListNode<T> end; // last node, /** * Remove by index. * * @param k index, start from 0, * @return value of removed node, or null if not removed, */ @Override public T remove(int k) { checkElementIndex(k); // find target node, and remember previous node, LinkedListNode<T> preNode = null; LinkedListNode<T> node = head; while (k-- > 0) { preNode = node; node = node.next; } T result = (T) node.value; // keep return value, removeNode(node, preNode); // remove return result; } /** * Remove by value, only remove the first occurrence, if any. * * @param v * @return whether removed, */ @Override public boolean removeValue(T v) { // find target node, and remember previous node, LinkedListNode<T> preNode = null; LinkedListNode<T> node = head; while (true) { if (node == null) return false;// not found, if (node.getValue().compareTo(v) == 0) break; // value found, preNode = node; node = node.next; } removeNode(node, preNode); // remove return true; } /** * Remove by value, remove all occurrences. * * @param v * @return count of nodes removed, */ @Override public int removeAllValue(T v) { int rc = 0; // find target node, and remember previous node, LinkedListNode<T> preNode = null; LinkedListNode<T> node = head; while (true) { if (node == null) return rc; // reach end, if (node.getValue().compareTo(v) == 0) { // value found, rc++; if (removeNode(node, preNode)) break; // remove, break if it's end, continue; // recheck this node, since it become the next node, } preNode = node; node = node.next; } return rc; } /** * Remove given node, which guarantee to exists. Also reduce the size by 1. * * @param node node to delete, * @param preNode previous node, could be null, * @return indicate whether removed node is end, */ protected boolean removeNode(LinkedListNode node, LinkedListNode preNode) { LinkedListNode nextNode = node.next; // next node, boolean isEnd = (nextNode == null); if (isEnd) { // target is end, if (preNode == null) { // target is also head, head = null; } else { // target is not head, thus preNode is not null, preNode.next = null; } end = preNode; } else { // target is not end, // replace target with next node, node.next = nextNode.next; node.value = nextNode.value; } size--; // reduce size by 1, return isEnd; } /** * Remove head node, * * @return */ @Override public T removeHead() { return remove(0); } /** * Remove end node, * * @return */ @Override public T removeEnd() { return remove(size - 1); }
boolean removeValue (T v)
, supprimer par valeur, supprimer uniquement la première occurrence, le cas échéant.
La logique est similaire à celle de la suppression par index.
Les différences sont:
int removeAllValue (T v)
, tout supprimer par valeur, supprimer toutes les occurrences.
Ceci est similaire à supprimer par valeur.
Différences:
removeNode ()
. booléen removeNode (nœud LinkedListNode, LinkedListNode preNode)
, supprimer par nœud, avec preNode donné.
Supprimez le nœud donné, dont l'existence est garantie, avec le nœud précédent donné, qui peut être nul.
La valeur de retour indique si le nœud supprimé est end, il est principalement utilisé pour prendre en charge removeAllValue()
.
T removeHead ()
, T removeEnd ()
, supprimez head / end.
Appelle simplement remove by index, avec l'index correspondant 0
et la size - 1
passés.
LinkedList
représente la liste liée, avec les champs size
, head
, end
et le type générique T
(pour le type de valeur dans le nœud), ce n'est pas thread-safe. checkElementIndex ()
, vérifie l'index donné et lance une exception si hors de portée. LinkedListNode
, représente le nœud dans la liste liée. avec les champs valeur
, suivant
. O(k)
O(n)
Où:
k
, est l'index de la cible. n
, est la taille de la liste liée. Depuis Java 8, il existe la méthode removeIf (Predicate super E> filter)
dans laquelle vous pouvez mettre votre propre condition.
list.removeIf(cur -> cur.item.equals(item));