在Java中实现链表(查找/删除节点)

在Java中实现链表(查找/删除节点),java,linked-list,Java,Linked List,我一直在编写一些代码,用java实现(编辑:单向)链表。我的主要问题是查找和删除节点,也就是说,使用Find(数据)告诉用户列表中是否存在节点;Delete(data)实际上是在找到节点后将其从列表中删除(或者如果找不到节点,则不执行任何操作)。Find(data)和Delete(data)使用相同的if-else逻辑,所以现在我只是将代码从Find方法复制到Delete方法中,Delete方法中有适当的指针来“跳过”已删除的节点 我想知道是否有更有效的方法。我曾想过在删除块中使用布尔值,例如:

我一直在编写一些代码,用java实现(编辑:单向)链表。我的主要问题是查找和删除节点,也就是说,使用Find(数据)告诉用户列表中是否存在节点;Delete(data)实际上是在找到节点后将其从列表中删除(或者如果找不到节点,则不执行任何操作)。Find(data)和Delete(data)使用相同的if-else逻辑,所以现在我只是将代码从Find方法复制到Delete方法中,Delete方法中有适当的指针来“跳过”已删除的节点

我想知道是否有更有效的方法。我曾想过在删除块中使用布尔值,例如:

public void Delete(data)
{
    if Find(data) 
    { 
        //code to delete node
    }
}

但由于当前节点可能位于头部、尾部或中间的某个地方,所以您仍然需要具有循环逻辑来检查您在何处,以便可以设置适当的引用。例如,如果用户希望删除尾部的节点,则前一个节点的下一个节点将设置为null。但是,在中间,您必须运行一个while循环来遍历列表,即

while (iter.NextNode !=null)
        {
            if (iter.NextNode.data == data)
            {
                iter.NextNode = iter.NextNode.NextNode;
                System.out.println(data + " was found in the list and removed"

                break;

            }
            else if (iter.NextNode.NextNode == null && iter.NextNode.data == data) 
            {//this is kinda weird. I couldn't use an else block, because either 
             //the code would never exit the loop, or it would keep running
                iter.NextNode = null;
                System.out.println(data + " was found in the list and removed. ");
                break;
            }

        iter = iter.NextNode;

        if (node.NextNode == null && node.data != data) 
        {//i guess I could have just put this if statement inside
         //the else block
            System.out.println(data + " was not found in the list.");
            break;
        }


        }
上面的代码块处理这两种情况

下面的代码块是我的查找(数据)方法:

}

如果问题不清楚:是否有一种方法可以在delete块中使用Find(data)方法,并删除所有逻辑

谢谢你的指导。我真的很感激

由于Find()方法不返回任何内容,因此不能在Delete()方法中使用它。 要集中Find()和Delete()的代码,请创建另一个私有方法getPreviousNode(int data),该方法返回所需节点的前一个节点

private Node getPreviousNode(int data) {
    Node iter = head;

    while (iter.NextNode != null) {
        if (iter.NextNode.data == data) {
            return iter;
        }

        iter.nextNode = iter.nextNode.nextNode;
    }

    return null;
}
在Find()和Delete()方法中调用此方法


回答您的评论:
仅写“prevNode.nextNode=prevNode.nextNode.nextNode”是不够的

考虑以下链接列表:

A[data=1 | nextNode=b]->b[data=4 | nextNode=c]->c[data=55 | nextNode=null]

其中,
A、 B,C:节点
a、 b、c:分别引用节点a、b和c。

B:要删除的节点

现在考虑删除节点的代码:

Node prevNode = getPreviousNode(data);
prevNode=a;//“a”是对getPreviousNode(4)返回的节点a的引用

node=b;//prevNode.nextNode为“b”

prev.NextNode=c;//node.nextNode是“c”

现在LinkedList是:

A[data=1 | nextNode=c]B[data=4 | nextNode=c]->c[data=55 | nextNode=null]

现在节点A有一个节点C的引用作为下一个节点。因此节点B与LinkedList解除链接 但没有从LinkedList中完全删除,因为节点B仍然具有节点C的引用 作为下一个节点。因此,必须删除此引用才能从LinkedList中完全删除节点B

所以下面的陈述是必要的

node.nextNode = null;
现在LinkedList是:

A[data=1 | nextNode=c]->c[data=55 | nextNode=null]

B[data=4 | nextNode=null]已从LinkedList中删除


您可以按照@SanjayChavan的建议共享
findPrevious
,但当您练习编写链表代码时,您会发现它已经很干净了,共享
findPrevious
并不能让它变得更好:

boolean Delete(int data)
{
    Node prev = null, node = null;
    for (node = head; node!=null; node=(prev=node).nextNode)
    {
        if (node.data == data)
        {
            if (prev!=null)
                prev.nextNode = node.nextNode;
            else
                head = node.nextNode;
            node.nextNode = null;
            return true;
        }
    }
    return false; 
}

Node Find(int data)
{
    for (Node node = head; node != null; node = node.nextNode)
    {
        if (node.data==data)
            return node;
    }
    return null;
}

一旦Sanjay的代码被修复,这样它就可以找到并删除
head
节点,它将比这更长更复杂。

查找和删除方法背后的逻辑是不同的。在“删除”中,需要指向要删除的节点之前的指针。但是,find方法可能只返回已找到的节点。为什么
find(int data)
方法不返回任何内容?如果它不返回对找到的
节点的引用
?@JonnyHenly即使他这样做,也不一定有助于删除,因为假设他的列表是单向的,他也需要上一个节点。@TimBiegeleisen你是对的,我假设是双链接列表。但是,OP的
Find(int data)
,如果是公共的,应该至少返回一个
布尔值
,如果不是
节点
…很抱歉,我发布的文本和代码不一致。当我说“上一个”节点时,我实际上是指当前节点,因为我可以通过说node.next=node.next.next来删除node.next;在上面,我说的是boolean,但我在尝试实现它时遇到了问题,所以在发布问题时,我将Find(data)的返回类型更改为void。再一次,很抱歉造成混乱。此外,是的,这是一个单向链表,上面已经对此进行了澄清。我不能说:prevNode.nextNode=prevNode.nextNode.nextNode?在注释中使用您的语句,您正在将前一个节点(prevNode)的引用从所需节点(要删除的节点)更改为下一个节点。但所需节点仍具有下一个节点的引用。因此它仍然与您的LinkedList连接。所以需要语句“node.nextNode=null”才能从列表中完全删除节点。在这个语句之后,您可以使“node=null”,这样所有对所需节点的引用都将被删除。另外,
getPrevious
修改
iter.nextNode
,我相信您不打算这样做
   public static ListNode search( List list, int target )
   {
      ListNode cursor = list.getFirst( );

      while( cursor != null )
      {
         if( cursor.getInfo( ) == target )
            return cursor;

         cursor = cursor.getLink( );
      }

      return cursor;
   }

   public void remove( int element )
   {
      ListNode cursor;
      ListNode target = search( this, element );

      if( isEmpty( ) )
         System.out.println( "There are no elements in this list." );

      if( target == null )
         System.out.println( element+" is not in this list." );
      else
      {
         if( head.getInfo( ) == element )
         {
            if( head.getLink( ) == null )
               head = null;
            else if( head == tail )
               tail = null;
            else
               head = head.getLink( );
         }
         else if( tail.getInfo( ) == element )
         { 
            for( cursor = head; cursor.getLink( ).getInfo( ) != element; cursor = cursor.getLink( ) )
            { }

            cursor.setLink( null );
            tail = cursor;
         }
         else
         {
            for( cursor = head; cursor.getLink( ).getInfo( ) != element; cursor = cursor.getLink( ) )
            { }

            cursor.setLink( cursor.getLink( ).getLink( ) );
         }
      }
   }
  prevNode.nextNode = node.nextNode;
node.nextNode = null;
boolean Delete(int data)
{
    Node prev = null, node = null;
    for (node = head; node!=null; node=(prev=node).nextNode)
    {
        if (node.data == data)
        {
            if (prev!=null)
                prev.nextNode = node.nextNode;
            else
                head = node.nextNode;
            node.nextNode = null;
            return true;
        }
    }
    return false; 
}

Node Find(int data)
{
    for (Node node = head; node != null; node = node.nextNode)
    {
        if (node.data==data)
            return node;
    }
    return null;
}
   public static ListNode search( List list, int target )
   {
      ListNode cursor = list.getFirst( );

      while( cursor != null )
      {
         if( cursor.getInfo( ) == target )
            return cursor;

         cursor = cursor.getLink( );
      }

      return cursor;
   }

   public void remove( int element )
   {
      ListNode cursor;
      ListNode target = search( this, element );

      if( isEmpty( ) )
         System.out.println( "There are no elements in this list." );

      if( target == null )
         System.out.println( element+" is not in this list." );
      else
      {
         if( head.getInfo( ) == element )
         {
            if( head.getLink( ) == null )
               head = null;
            else if( head == tail )
               tail = null;
            else
               head = head.getLink( );
         }
         else if( tail.getInfo( ) == element )
         { 
            for( cursor = head; cursor.getLink( ).getInfo( ) != element; cursor = cursor.getLink( ) )
            { }

            cursor.setLink( null );
            tail = cursor;
         }
         else
         {
            for( cursor = head; cursor.getLink( ).getInfo( ) != element; cursor = cursor.getLink( ) )
            { }

            cursor.setLink( cursor.getLink( ).getLink( ) );
         }
      }
   }