从单链表的头部删除

时间:2018-01-06 09:24:25

标签: java data-structures linked-list

我正在编写自己的链接列表实现,如下所示,当我尝试执行操作' deleteElementFromHead'链接列表,我很好奇我所做的是否足够?  从头部删除元素的方法如下,

public void deleteAtHead()
{
        Node secondNode = this.head.next;
        this.head = secondNode;
        count--;
}

我怀疑在交换指针以删除头部的元素时,旧的head元素仍然在内存中,垃圾收集器可能收集也可能不收集。我是否需要将已删除的元素设置为null,或者需要在上述方法中添加一些其他代码以避免内存泄漏。

链表的完整代码如下,

package com.nobalg.Linkedist;

public class Node implements Operations {
int data;
Node next,head,tail;
int count = 1;
public Node(int data)
{
    this.data = data;
    this.head=this;
    this.tail = this;
}

/**********This method takes O(n) time************/
public void addNode(int nodeData)
{
    Node node =  new Node(nodeData);
    Node temp = this;
    while(temp.next!=null){
         temp = temp.next;
    }
    temp.next = node;
    count++;
}

/******This operation takes O(1) time********/
public void addAtTail(int nodeData)
{
    Node node = new Node(nodeData);
    tail.next = node;
    tail = tail.next;
    count++;
}

/********This operation takes O(1) time**************/
public void addAtHead(int nodeData)
{
    Node node = new Node(nodeData);
    node.next = head;
    this.head = node;
    count++;
}

/************This operation takes  O(n) time****************/
public void addAtIndex(int index,int nodeData)
{
    if(index < 0 || index >count)
    {
        throw new IllegalStateException();
    }
    Node node =  new Node(nodeData);
    Node tempLast = this.head;
    Node tempCurrent = this.head;
    int locCount = 0;
    while(locCount!=index){
        tempLast = tempCurrent;
        tempCurrent = tempCurrent.next;
        locCount++;
    }
    node.next = tempCurrent;
    if(index == 0)this.head = node;
    else tempLast.next = node;
    count++;
}

/**********This operation takes O(n) time in case of singly linked list*************/
public void deleteAtTail()
{
    Node temp = this.head;
    Node locLastNode = null;
    while(temp.next!=null)
    {
        locLastNode = temp;
        temp = temp.next;
    }
    this.tail = locLastNode;
    locLastNode.next = null;
    count--;
}

public void deleteAtHead()
{
    Node secondNode = this.head.next;
    this.head = secondNode;
    count--;
}

public void deleteAtIndex()
{
    //implementation pending
}
public int size()
{
    return count;
}

public void display()
{
    Node temp = this.head;
    for(int  i = 0 ; i < count; i++)
    {
        System.out.println(temp.data);
        temp = temp.next;
    }
}
  }

5 个答案:

答案 0 :(得分:1)

以下代码

public void deleteAtHead()
{
        Node secondNode = this.head.next;
        this.head = secondNode;
        count--;
}

有一些边缘情况丢失,就像它会抛出NPE,当LL为空而另一个是它只有1个节点时。无论如何,你的问题如下: -

  

我怀疑在交换指针时删除元素   头部,旧头元素仍在记忆中,可能会也可能不会   被垃圾收集者收集。我是否需要设置已删除   元素为null,或者需要在上面添加一些其他代码   避免内存泄漏的方法。

所以是的,在这种情况下,旧的head元素仍然会在内存中,但它不会指向你的LL的头部,所以你不会得到错误的结果。 GC运行一段时间后,无论你是否将它设置为 NULL ,它都会被它收集。

详细了解在此SO答案中明确指定 NULL 时会发生什么: - Does assigning objects to null in Java impact garbage collection?

答案 1 :(得分:0)

我猜你错过了尾部和头部指向同一节点的情况之一。假设只有一个元素,并且您调用deleteAtHead()。在这种情况下,Node有两个引用,一个是head,另一个是tail,您只是取消引用(this.head = secondNode; count--;)头节点,{{{ 1}}节点。是不是仍然引用第一个节点。这是你的程序中断。你应该考虑这个案子。如果任何对象没有引用,那么您不需要担心该对象,GC将收集/释放该对象。但是您需要确保正确地取消引用所有这些对象。

答案 2 :(得分:0)

垃圾收集器自动在JVM的后台运行。 如果资源没有分配给任何变量或者没有给出任何引用,它将被垃圾收集器清理。

以下是在某个位置删除的代码。

    Node deleteAtIndex(Node head, int position) {
        Node temp = head;
        if(head == null)
            return null;
        else if(position == 0){
            head=head.next;
        }
        else{
            int currentIndex = 0;
            while(temp != null && currentIndex <= position-2){
                currentIndex++;
                temp=temp.next;
            }
            Node temp2 = temp.next.next;
            temp.next=temp2;
        }
        return head;
    }

答案 3 :(得分:0)

  

旧的头部元素仍然在内存中,可能会也可能不会   由垃圾收集器收集。我是否需要设置已删除   元素为null,或者需要在上面添加一些其他代码   避免内存泄漏的方法

所以,你需要理解这一点,JVM负责GC,你不需要那么多的控制。此外,设置null并不意味着您可以立即获得分配的内存。

例如:

Object obj = new Object ();

在JVM中创建一个对象并分配\ reserve内存。现在,设置obj=null表示obj具有null引用,但分配的内存仍然存在,没有引用(并且符合GC条件)。

答案 4 :(得分:0)

交换指针

Node secondNode = this.head.next;
this.head = secondNode;
count--;

在上面的代码片段中,旧元素仍然保留在内存中,这就是悬空指针的情况。 对于您的问题如何从堆中释放内存,请参阅this question

您也可以在一行this.head = this.head.next中编写此内容,JVM很可能会处理垃圾收集......

然而,坚持你写的两行。这是一种更好的方法。

希望这会有所帮助:)