[英]How to remove a specific value from linked list in Java?
How to remove a specific value from a linked list java? 如何从链表java中删除特定值?
I tried to make it in my implementation, but it wasn't easy.. 我试图在我的实现中实现它,但这并不容易..
Here is what I'm trying to make: 这是我想要做的:
//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;
}
These are the pre-setup: 这些是预先设置:
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;
}
And the main function: 主要功能:
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);
}
}
And I have a result like this. 我有这样的结果。 It doesn't change at all..
它根本不会改变..
a b c a b d b abba a z a Remove some of elements. a b d b abba a z a
It only erase value c
. 它只消除了值
c
。 I don't know why. 我不知道为什么。
As per the details of question,i assume you are fairly new in Java. 根据问题的细节,我假设你是Java的新手。 What you are asking and the details you are showing are totally different.
你问的问题和你展示的细节是完全不同的。
LinkedQueue<String> q = new LinkedQueue<String>();
is only applicable if LinkedQueue is a genreic class not a specific impl for Item type class. 仅当LinkedQueue是一个genreic类而不是Item类的特定impl时才适用。 ie you are not creating object of
LinkedQueue<Item>
class. 即你没有创建
LinkedQueue<Item>
类的对象。 LinkedQueue<String> and LinkedQueue<Item>
is different. LinkedQueue<String> and LinkedQueue<Item>
是不同的。
cur.equals(item)
lack of knowledge of equal contract and difference in == vs equal
. cur.equals(item)
缺乏对平等合同和== vs equal
差异的知识。 ie you are comparing a two totally different object. 即你正在比较两个完全不同的对象。 One is a Node and other is Item class object.
一个是Node,另一个是Item类对象。
Suggestion: clear basics, Read book by cathy Sierra.Scjp Sun Certified Programmer for Java 6 建议:明确的基础知识,阅读由cathy Sierra.Scjp Sun认证的Java 6程序员
As for answer, you are literally not calling remove from main (test it via a print statement in remove method). 至于答案,你实际上不是从main调用remove(在remove方法中通过print语句测试它)。 That is why you keep getting same answer.
这就是为什么你一直得到相同的答案。
Note: Your really not can't digest real solution even if we tell. 注意:即使我们告诉你,你真的不能消化真正的解决方案。
Following code snippet contains various remove()
methods, taken from one of my LinkedList
implementation, written in Java
. 以下代码片段包含各种
remove()
方法,这些方法取自我用Java
编写的LinkedList
实现之一。
LinkedList.java (partly) LinkedList.java (部分)
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);
}
LinkedListTest.java (partly) LinkedListTest.java (部分)
(unit test, via TestNG
) (单元测试,通过
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,
}
}
All test cases would pass. 所有测试用例都会通过。
Methods: 方法:
T remove(int k)
, remove by index. T remove(int k)
,按索引删除。 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,
boolean removeValue(T v)
, remove by value, only remove first occurrence, if any. boolean removeValue(T v)
,按值删除,仅删除第一个匹配项(如果有)。
The logic is similar as remove by index. 逻辑类似于按索引删除。
The differences are: 不同之处是:
int removeAllValue(T v)
, remove all by value, remove all occurrences. int removeAllValue(T v)
,删除所有值,删除所有匹配项。
This is similar as remove by value. 这类似于按值删除。
Differences: 区别:
removeNode()
. removeNode()
的返回值。 boolean removeNode(LinkedListNode node, LinkedListNode preNode)
, remove by node, with preNode given. boolean removeNode(LinkedListNode node, LinkedListNode preNode)
,逐节点删除,给定preNode。
Remove given node, which is guaranteed to exists, with previous node given, which might be null. 删除给定节点,该节点保证存在,给定前一个节点,该节点可能为null。
Return value indicate whether removed node is end, it's mainly used to support removeAllValue()
. 返回值表示删除的节点是否结束,它主要用于支持
removeAllValue()
。
T removeHead()
, T removeEnd()
, remove head / end. T removeHead()
, T removeEnd()
,删除头/尾。
Simply calls remove by index, with corresponding index 0
and size - 1
passed. 只需通过索引调用remove,并传递相应的索引
0
和size - 1
。
Tips: 提示:
LinkedList
represent linkedlist, with fields size
, head
, end
, and generic type T
(for value type in node), it's not thread-safe. LinkedList
表示链表,包括字段size
, head
, end
和泛型类型T
(对于节点中的值类型),它不是线程安全的。 checkElementIndex()
method, check given index, and throw exception if out of range. checkElementIndex()
方法,检查给定索引,如果超出范围则抛出异常。 LinkedListNode
, represent the node in linked list. LinkedListNode
表示LinkedListNode
的节点。 with fields value
, next
. value
, next
。 O(k)
O(k)
O(n)
O(n)
Where: 哪里:
k
, is the index of target. k
,是目标的索引。 n
, is size of linkedlist. n
,是链表的大小。 从Java 8开始,有removeIf(Predicate<? super E> filter)
方法可以放置自己的条件。
list.removeIf(cur -> cur.item.equals(item));
In your if statement you are checking if the cur
Node
is equal to the Item
passed in: if (cur.equals(item))
. 在if语句中,您正在检查
cur
Node
是否等于传入的Item
: if (cur.equals(item))
。
I think you should be checking if the Item
stored in the cur
Node
is equal to the Item
passed into your function: if (cur.item.equals(item))
. 我想你应该检查,如果
Item
存储在cur
Node
等于Item
传递到你的函数: if (cur.item.equals(item))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.