Java 使用头和尾引用删除元素的单链表

Java 使用头和尾引用删除元素的单链表,java,reference,linked-list,Java,Reference,Linked List,我必须为我的项目实现一个单链表,而且我很难让remove方法正常工作。我在这里搜索了答案,但我找不到任何包含尾部引用的答案。我的项目需要在列表中有一个头尾参考,并需要在必要时进行更新。这是我的类和remove方法: public class BasicLinkedList<T> implements Iterable<T> { public int size; protected class Node { protected T data; protec

我必须为我的项目实现一个单链表,而且我很难让remove方法正常工作。我在这里搜索了答案,但我找不到任何包含尾部引用的答案。我的项目需要在列表中有一个头尾参考,并需要在必要时进行更新。这是我的类和remove方法:

public class BasicLinkedList<T> implements Iterable<T> {
public int size;

protected class Node {
    protected T data;
    protected Node next;

    protected Node(T data) {
        this.data = data;
        next = null;
    }
}

protected Node head;
protected Node tail;

public BasicLinkedList() {
    head = tail = null;
}

public BasicLinkedList<T> addToEnd(T data) {
    Node n = new Node(data);
    Node curr = head;
    //Check to see if the list is empty
    if (head == null) {
        head = n;
        tail = head;
    } else {
        while (curr.next != null) {
            curr = curr.next;
        }
        curr.next = n;
        tail = n;

    }
    size++;
    return this;
}

public BasicLinkedList<T> addToFront(T data) {
    Node n = new Node(data);
    if(head == null){
        head = n;
        tail = n;
    }
    n.next = head;
    head = n;
    size++;
    return this;
}

public T getFirst() {
    if (head == null) {
        return null;
    }
    return head.data;
}

public T getLast() {
    if(tail == null){
        return null;
    }
    return tail.data;
}

public int getSize() {
    return size;
}

public T retrieveFirstElement() {
    // Check to see if the list is empty
    if (head == null) {
        return null;
    }
    Node firstElement = head;
    Node curr = head.next;
    head = curr;
    size--;
    return firstElement.data;

}

public T retrieveLastElement() {
    Node curr = head;
    Node prev = head;
    // Check to see if the list is empty
    if (head == null) {
        return null;
    } else {
        // If there's only one element in the list
        if (head.next == null) {
            curr = head;
            head = null;
        } else {
            while (curr.next != null) {
                prev = curr;
                curr = curr.next;
            }

            tail = prev;
            tail.next = null;
        }
    }
    size--;
    return curr.data;
}

public void remove(T targetData, Comparator<T> comparator) {
    Node prev = null, curr = head;
    while (curr != null) {
        if (comparator.compare(curr.data, targetData) == 0) {
            //Check to see if we need to remove the very first element
            if (curr == head) {
                head = head.next;
                curr = head;
            } 
            //Check to see if we need to remove the last element, in which case update the tail
            else if(curr == tail){
                curr = null;
                tail = prev;
                prev.next = null;
            }
            //If anywhere else in the list
            else {
                prev.next = curr.next;
                curr = curr.next;
            }
            size--;
        } else {
            prev = curr;
            curr = curr.next;
        }
    }
}

public Iterator<T> iterator() {
    return new Iterator<T>() {

        Node current = head;

        @Override
        public boolean hasNext() {
            return current != null;
        }

        @Override
        public T next() {
            if(hasNext()){
                T data = current.data;
                current = current.next;
                return data;
            }
            return null;
        }

        @Override
        public void remove(){
            throw new UnsupportedOperationException("Remove not implemented.");
        }

    };
}
public类BasicLinkedList实现了Iterable{
公共整数大小;
受保护类节点{
受保护的T数据;
受保护节点下一步;
受保护节点(T数据){
这个数据=数据;
next=null;
}
}
受保护节点头;
受保护的节点尾部;
公共基本分类表(){
头=尾=空;
}
公共基础ClinkedList addToEnd(T数据){
节点n=新节点(数据);
节点电流=头部;
//检查列表是否为空
if(head==null){
水头=n;
尾=头;
}否则{
while(curr.next!=null){
curr=curr.next;
}
curr.next=n;
尾=n;
}
大小++;
归还这个;
}
公共基础ClinkedList addToFront(T数据){
节点n=新节点(数据);
if(head==null){
水头=n;
尾=n;
}
n、 下一个=头部;
水头=n;
大小++;
归还这个;
}
公共T getFirst(){
if(head==null){
返回null;
}
返回头数据;
}
公共T getLast(){
if(tail==null){
返回null;
}
返回tail.data;
}
公共int getSize(){
返回大小;
}
公共T retrieveFirstElement(){
//检查列表是否为空
if(head==null){
返回null;
}
节点第一个元素=头;
节点curr=head.next;
水头=电流;
大小--;
返回firstElement.data;
}
公共T RetrieveLasteElement(){
节点电流=头部;
节点prev=头部;
//检查列表是否为空
if(head==null){
返回null;
}否则{
//如果列表中只有一个元素
if(head.next==null){
curr=头;
head=null;
}否则{
while(curr.next!=null){
上一次=当前;
curr=curr.next;
}
尾部=上一个;
tail.next=null;
}
}
大小--;
返回当前数据;
}
公共无效删除(T targetData、比较器、比较器){
节点prev=null,curr=head;
while(curr!=null){
if(比较器比较(当前数据,目标数据)==0){
//检查是否需要删除第一个元素
如果(当前==水头){
head=head.next;
curr=头;
} 
//检查是否需要删除最后一个元素,在这种情况下更新尾部
else if(curr==tail){
curr=null;
尾部=上一个;
prev.next=null;
}
//如果列表中还有其他地方
否则{
上一个=当前下一个;
curr=curr.next;
}
大小--;
}否则{
上一次=当前;
curr=curr.next;
}
}
}
公共迭代器迭代器(){
返回新的迭代器(){
节点电流=头;
@凌驾
公共布尔hasNext(){
返回电流!=null;
}
@凌驾
公共交通工具{
if(hasNext()){
T数据=当前数据;
当前=当前。下一步;
返回数据;
}
返回null;
}
@凌驾
公共空间删除(){
抛出新的UnsupportedOperationException(“删除未实现”);
}
};
}
}

我已经经历了很多次这种方法的迭代,每次我要么丢失头部引用,要么丢失尾部引用,要么不删除元素,我都被难住了。作为参考,这里是我正在运行的测试。我甚至没有考试不及格,它只是说不及格

public void testRemove(){
            BasicLinkedList<String> basicList = new BasicLinkedList<String>();
    basicList.addToEnd("Blue");
    basicList.addToEnd("Red");
    basicList.addToEnd("Magenta");
    //Blue -> Red -> Magenta -> null
    basicList.remove("Red", String.CASE_INSENSITIVE_ORDER);
    //Blue -> Magenta -> null
    assertTrue(basicList.getFirst().equals("Blue"));
    //getLast() returns the tail node
    assertTrue(basicList.getLast().equals("Magenta"));
    }
public void testRemove(){
BasicClinkedList basicList=新的BasicClinkedList();
basicList.addToEnd(“蓝色”);
基本列表addToEnd(“红色”);
basicList.addToEnd(“洋红”);
//蓝色->红色->洋红->空
basicList.remove(“红色”,字符串。不区分大小写(顺序));
//蓝色->洋红->空
assertTrue(basicList.getFirst().equals(“蓝色”);
//getLast()返回尾部节点
assertTrue(basicList.getLast().equals(“洋红”);
}

编辑:忘记提到删除方法应该从列表中删除目标数据的所有实例。

我只看到一个错误。如果列表最初为空,则以下方法将导致一个循环,其中一个节点的下一个节点引用自身:

public BasicLinkedList<T> addToFront(T data) {
    Node n = new Node(data);
    // The list was empty so this if is true
    if(head == null){
        head = n;
        tail = n;
    }
    n.next = head;
    // now head == n and n.next == head == n so you've got a circle
    head = n;
    size++;
    return this;
}
public基本列表addToFront(T数据){
节点n=新节点(数据);
//列表为空,因此这是真的
if(head==null){
水头=n;
尾=n;
}
n、 下一个=头部;
//现在head==n和n.next==head==n,所以你们有一个圆
水头=n;
大小++;
归还这个;
}
您可以这样解决此问题:

public BasicLinkedList<T> addToFront(T data) {
    Node n = new Node(data);
    if(head == null){
        tail = n;
    }
    n.next = head;
    head = n;
    size++;
    return this;
}
public基本列表addToFront(T数据){
节点n=新节点(数据);
if(head==null){
尾=n;
}
n、 下一个=头部;
水头=n;
大小++;
归还这个;
}

最近新用户提出了太多糟糕的问题,我觉得有义务在评论中告诉你“干得好!”。干得好+1添加其余的代码
iterator
getFirst
getLast
addToEnd
我想用remove方法隔离问题,但我想问题也可能存在于其他地方。现在全班都加入了@Marquisblount你的代码没有任何问题我得到了预期的结果你能提供你所遇到的错误吗seeing@MarquisBlount我想我可能已经修复了这个问题,并在之后发布了修复代码。移除