双向链表的Remove()方法

时间:2017-10-31 22:44:03

标签: java list data-structures doubly-linked-list

 /**
 * The remove() method removes the current node from the list. If the next node exists,
 * it becomes the current node. Otherwise the previous node becomes the current node. 
 * If neither node exists, the list becomes empty.
 * 
 * @throws Exception    If the list is empty.
 */

public void remove() throws Exception
{
    if (isEmpty())
    {
        throw exListEmpty;
    }
    Node target = current;      
    Node prevNode = target.prev;
    Node nextNode = target.next;

    // current node is at head
    if (prevNode == null)
    {
        nextNode.prev = null;
        head = nextNode;
    }
    else
    {
        prevNode.next = nextNode;
        current = prevNode;
    }

    // current node is at tail
    if (nextNode == null)
    {
        prevNode.next = null;
        tail = prevNode;
    }
    else
    {
        nextNode.prev = prevNode;
        current = nextNode;
    }
    if (prevNode == null && nextNode == null)
    {
        isEmpty();
    }
    else if (prevNode != null && nextNode != null)
    {
        prevNode.next = nextNode;
        nextNode.prev = prevNode;
        current = nextNode;
    }
    size--; 
}

测试代码是:

    public void testContains() throws Exception
    {
        PDLinkedList first = new PDLinkedList();
        first.append(5);
        first.insert(7);
        first.add(8);

        System.out.println("Before first remove: " + first.toString());
        first.remove(); 
        System.out.println("After first remove: " + first.toString());
        first.remove(5);
        System.out.println("After second remove: " + first.toString());
        first.remove();
        System.out.println("After third remove: " + first.toString());
    }

然后将其打印为:

Before first remove: 7 8 5
After first remove: 7 8 5
After second remove: 7 8
After third remove: 7 8

它应该在第一个remove()之后删除8,然后在第三个remove()之后删除7。我的add(item)方法被设置为当前指针,然后我的remove()方法应该删除当前指针处的节点。但似乎什么也没做。我想知道它是否指向错误的节点?代码编译,但我收到一个断言错误,指出7和8仍然在列表中。

1 个答案:

答案 0 :(得分:2)

考虑在5种不同的情况下删除节点:

  1. 列表为空
  2. 列表仅包含一个元素
  3. 目标节点位于开头
  4. 目标节点在最后
  5. 目标节点位于其他位置
  6. 不要在一个长函数中混合所有内容,将其分解为相应的步骤:

    (1)很简单,只需返回

    (2)您将headlast都指向null

    (3)您将head分配给head.next,将head.previous分配给nullhead已经是"新" head)

    void RemoveAtStart()
    {
        if (IsEmpty())
        {
            return;
        }
    
        if (Head == Last)
        {
            Head = null;
            Last = null;
        }
        else
        {
            Head = Head.Next;
            Head.Previous = null;
        }       
    }
    

    (4)非常相似:last变为last.previouslast.next变为nulllast为"新"最后)

    void RemoveAtEnd()
    {
        if (IsEmpty())
        {
            return;
        }
    
        if (Last == Head)
        {
            Last = null;
            Head = null;            
        }
        else
        {
            Last = Last.Previous;
            Last.Next = null;
        }       
    }
    

    (5)您找到target,然后将target.previous.next指向target.next("左"目标节点跳过它,并指向目标的右侧节点)。然后,如果目标不是最后一个,请将target.Next.Previous指向target.Previous

    然后结合所有案例1-5

    void Remove(Node<T> node)
    {
        if (IsEmpty())
        {
            return;
        }
    
        if (Head == Last)
        {
            Head = null;
            Last = null;
        }
        else if (node == Last)
        {
            RemoveAtEnd();
        }
        else if (node == Head)
        {
            RemoveAtStart();
        }
        else
        {
            Node<T> current = Head;
            while (current != node)
            {
                current = current.Next;
            }
            current.Previous.Next = current.Next;
            if (current.Next != null)
            {
                current.Next.Previous = current.Previous;
            }        
            current = null;        
        }       
    }