先学习有关链表的储存知识
本图截取自代码随想录 (programmercarl.com)
构造链表
public class ListNode{
//结点的值
int val;
//下一个节点
ListNode next;
//构造函数
public ListNode(){}
public ListNode(int val)
{
this.val=val;
}
public ListNode(int val,ListNode next){
this.val=val;
this.next=next;
}
删除链表节点时,只需要把上一个链表的next指针指向下下个节点即可。
在Java中,当删除链表节点时,内存回收是通过垃圾回收器(Garbage Collector)来处理的,而不是特定于删除节点的回收机制。
当你删除一个链表节点时,实际上是将该节点从链表中移除,并且没有任何变量引用指向该节点时,它就成为了不可达对象。当垃圾回收器执行时,会检测并回收不可达的对象,释放它们所占用的内存。
垃圾回收器使用的算法和策略因Java虚拟机的不同实现而异,常见的垃圾回收算法包括标记-清除算法(Mark and Sweep)、复制算法(Copying)、标记-整理算法(Mark and Compact)等。这些算法的具体实现可能会考虑多个因素,如堆内存的分代结构、停顿时间等。
因此,当你删除链表节点时,你只需要确保没有直接或间接的引用指向这个节点,然后让垃圾回收器自动负责回收不可达的节点和释放相关的内存空间。无需特定的回收机制来处理单个节点的删除操作。
class Solution {
public ListNode removeElements(ListNode head, int val) {
if(head==null)
return head;
//设置虚拟头结点
ListNode phead=new ListNode(0,head);
ListNode cur=head;
ListNode pre=phead;//这里注意:pre和cur都是指针 只需要把他们指向现存节点即可 不能重新new
while(cur!=null)
{
if(cur.val==val)
{
pre.next=cur.next;//删除该节点 删除操作通过pre来进行
cur=cur.next;
}else{
pre=cur;
cur=cur.next;
}
}
return phead.next;
}}
最重要的是pre和cur是两个指针而不是节点,移除操作是通过改变pre.next的指向来进行的。
注意for循环里的条件,(i=0;i<=index;i++)平时我们一般的循环都是i<index,这里因为虚拟头结点的存在,如我们想操作链表中第一个元素也就是索引为0的元素,要让cur指向这个元素
int get(int index) {
if(index<0||index>=size)
return -1;
ListNode cur=head;
for(int i=0;i<=index;i++)
{
cur=cur.next;
}
return cur.val;
}
首先注意:向中添加一个节点需要两步:想要在index处插入节点,只需要操作pre即可。
newnode.next=cur.next;
cur.next=newnode;
想要删除索引为x的节点,设x-1处的节点为pre,x处为cur,这个时候虚拟头节点的作用就体现出来了。
ListNode pred = head;
for (int i = 0; i < index ; i++) {
pred = pred.next;
}
pre.next=pre.next.next;