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

时间:2015-10-13 02:05:30

标签: java linked-list

我一直在研究一些代码来实现java中的(edit:单向)链表。我的主要问题是在查找和删除节点时,即使用查找(数据)告诉用户列表中是否存在节点;删除(数据)实际上会在找到节点后从列表中删除节点(如果找不到节点则不执行任何操作)。查找(数据)和删除(数据)使用相同的if-else逻辑,所以现在我只是将Find方法中的代码复制到delete方法中,在delete方法中使用适当的指针来"跳过&# 34;已删除的节点。

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

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

但由于当前节点可能位于头部,尾部或中间的某个位置,因此您仍需要使用循环逻辑来检查您的位置,以便设置适当的引用。例如,如果用户想要删除尾部的节点,则前一节点的下一个节点将被设置为空。但是,在中间,你必须运行一个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;
        }


        }

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

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

public void Find(int data)
{
    Node node = head;
    if (head == null)
    {
        System.out.println("No nodes found. ");

    }


    else if (node.NextNode==null)
    {
        if (node.data == data)
        {
            System.out.println( data + " was found in the list.");

        }
        else
        {
            System.out.println("That value was not found in the list.");

        }
    }
    else
    {
        while (node.NextNode !=null)
        {
            if (node.data == data)
            {
                System.out.println(data + " was found in the list.");
                break;

            }
            else if (node.NextNode.NextNode == null && node.NextNode.data == data)
            {
                System.out.println(data + " was found in the list.");
                break;
            }
            else    
            {
                node = node.NextNode;
            }
            if (node.NextNode == null && node.data != data)
            {
                System.out.println(data + " was not found in the list.");
                break;
            }
        }

    }

}

如果问题不清楚:有没有办法在删除块中使用我的Find(数据)方法,并取出所有逻辑?

感谢您的指导。我真的很感激!

3 个答案:

答案 0 :(得分:0)

由于您的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()方法中调用此方法。

void Find(int data) {
    // Code to handle head & tail conditions

    Node prevNode = getPreviousNode(data);

    if (prevNode != null) {
        System.out.println("Found");
    }

    ...
}

void Delete(int data) {
    // Code to handle head & tail conditions

    Node prevNode = getPreviousNode(data);

    if (prevNode != null) {
        Node node = prevNode.nextNode;
        prevNode.nextNode = node.nextNode;
        node.nextNode = null;
        System.out.println("Found & Deleted");
    }

    ...
}

回答你的评论:
只写“prevNode.nextNode = prevNode.NextNode.NextNode”是不够的。

考虑使用LinkedList:

  

A [data = 1 | nextNode = b] - > B [data = 4 | nextNode = c] - > C [数据= 55 | nextNode = null]

其中,
A,B,C:节点
a,b,c:分别参考节点A,B和C.

B:要删除的节点

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

Node prevNode = getPreviousNode(data);
  

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

if (prevNode != null) 
  node = prevNode.nextNode;
  

node = b; // prevNode.nextNode是'b'

  prevNode.nextNode = node.nextNode;
  

prev.NextNode = c; // node.nextNode是'c'

现在LinkedList是:

  

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

现在,节点A将节点C的引用作为nextNode。因此节点B与LinkedList断开链接 但是没有完全从LinkedList中删除,因为节点B仍然具有Node C的引用 作为NextNode。因此,您必须删除此引用才能从LinkedList中完全删除Node B.

所以下面的陈述是必要的

node.nextNode = null;

现在LinkedList是:

  

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

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

答案 1 :(得分:0)

您可以像@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节点,它会比这更长,也更复杂。

答案 2 :(得分:0)

   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( ) );
         }
      }
   }