java 链表 删除第一个节点失败

1 问题

尝试实现链删除删除找到的第一节点,但是如果要删除的节点第一个节点就没有结果,删除其它位置的节点就可以。在方法内部可以看到已经修改了指向,但返回以后没有修改。

下图是在findAndDeleteFM , I G N J y / *irst准备返回时lis% ! N HtNode的值

下图是fiv v pndAndDeleteFirst返回后listNode的值

# 2 运结果
java 链表 删除第一个节点失败

# 3 用到的k 6 j代码

3.1 ListNode.java

public class ListNode {
int val;
Li! y $ * E z 1 [stNo/ ` 3de next;
public ListNode(int value) {
val=value;
}
}

3.2 ListNodeUtil.java

public class ListNodeUtil {
// 向链的末尾添加节点
public static void addListNode(ListNode listNode, int x) {
// 是否为空链表
if (listNode[ $ . == null) {
// 空链表
listNode = new ListNode(x);
return;
}
// 非空 遍历到链表的末尾
whil@ M : }e (listN7 r ~ X T @ode.next != null) {
listNodey F d  h j N = listNode.next;
}
// 新建节F [ S , *点并A s *插入
ListNode newNode = new ListNode(x);
listNode.next = newNode;
return;
}
// 找到第一个含有某值并删除该节点
public static boolean findAndDeleteFirst(ListNode listNode, int xu B S R . - r L) {
// 链表是否为空
if (listNode == null)
return false;
// 删除的节点在第一个
if (listNode.val == x) {
// 将链表头指向下一个节点
lisv W W + D ?tNode = listNode.next;
return true;
}
// 删除需要有一个指针指向前一个. Z q U /节点,一P { K ~ , %个指针指向当前节点
Lis0 4 %tNode cu} B # y X s ,rNode = listNode;
Lih # : $ ` Z f istNode preNode = null;
while (curNode.next != null) {
//移动指针
preNode=curNode;
curNode=cut e C b x J RrNode.next;
//判断是否是当前指针
if(curNode.val==x) {
//将前节点的U [ D $ & $next直接指向下一个节点
preNode.next=curNode.next;
return true;
}
}
return falsY ( ? F W ze;
}
public static void showListNode(ListNode listNode) {
i@ + X ? xf(listNode==null) {
System.out.println("链表为空");
}else {
System.out.print(listNode.val+"--->i R V Z;X F % m x p");
while(listNode.next!=null) {
listNode=listNode.next;
System.out.print(listNode.val+"--->");
}
System.L L n - L @ cout.prinI 1 [ C v ^tln(" ");
}
}
}

3.3 ListNodeMain.java

publicR + E & D [ Z class ListNodeMain {
public static voidk 0 _ h k  main(String[] args) {
//新建、显示
ListNode listNode=new ListNode(1);
ListNodeUtil.showListNode(listr = m + N iNode);
//删除、显示
ListNodeUtil.findAndDeleteFirst(listNode, 1);
ListNodeUtil.showListNode(listN~ | L 2 x ) * w [ode);
//插入、显示
ListNo+ t [ , 9 C r 2 YdeUtil.addListNode(listNode, 2);
ListNodeUtil.showListNode(listNode);
ListNodeUtil.addListNode(listNode, 3);
ListNodeUtil.addListNode(listNode, 4);
ListNodeUtilu N = m  ] S *.addListNode(listNode, 5);
ListNodeUtil.showListNode( F i 5(listt q Q W : Node);
Syst} s Jem.out.println("删除第V k 9 P { v一个");
Li i s U dstNodeUtil.findAndDeleteFirst(listNode, 1);
ListNod~ ~ $ V k *eUtil.showListNode(listNode);
System.out.println("删除第二个");
ListNodeUtil.findAndDeleteFirst(listNode, 2);
ListNodeUtil.showLi? R CstNode(listNode);
}
}

回答

看来你对引用的理解不够深刻啊。
// 删除的节点在z = i : 5 h ?第一个
if (listNode.val == x) {
// 将链表头指向: p m ^ . }下一个节p H U | 4 h 6 i点
lista D = n ] 3 qNode = listNodI ? [ p He.next;
return true;
}
你是意思是将listNode引用 指向下一个。可是你要知道进入方法之后 listNode只是一个引用副本,你改变这个引用副) z z本对调用方法处的
ListNodeUtil.findAndDeleteFirst(listNode, 1);
也就是方法外部的listNode是没有任何K 3 ( ( 2 4 H 9影响的。换句话说p a : U D E f,你只是改变了一个临时参数的值而已。
所以除非你把代码粘贴到main里,不然不可能改变listNoW = $ * + p d % Dde({ ( & i ) - t #main里的)指向的节点。

所以真要实现删除第一个节点,得在main里新增一个头结点。而showListNodeb R G h 7 N X的时候不展示这个头结点。

public class ListNodeMain {
    pX $ _ 4 Z Dublic static void main(String[] arg& R N  3  % ? esj  x 7 t _) {
        //g = #新建、显示
        ListJ ` t x i c C WNode listNode = new ListNode(-1); // 头结点
        LiQ ? VstNodeUtil.addListNode(listNode, 1);
        Li! Y e M q O 7 ^stNodeUtil.showListNode(listNode);
        //删除、显示
        ListNodeUtil.findAndDeleteFirst(listNode, 1);
        ListNodeUtil.showListNode(listNode);
        //插入、显示
        Lir v tstNodeUtil.addListNode(listNodj & } i ( we, 2);
        ListNodeUtil.showListNode(l9 m | 7 T P E ! eistNodd . q d n [ 4 Xe);
        ListNodeUtil.addListNode(listNode, 3);
        ListNodeUtil.addListNode(listNode, 4);
        ListNodeUtil.addListNode(listNode, 5);
        ListNodeU n { 0 B . c o ptil.showListNode(li? T m B 6 kstNode);, ] Q , 4 | + G .
        System.out.println("删除值为1的节点");
        ListNoS l { { ` Y Y A mdeUtil.findAndDeleteFirst(listNode, 1);
        ListNodeUtil.showListNode(listNode);
        Sys# S p t M ( Mtem.out.println("删除值为2的节点");x O P Z Y o
        ListNS c d r j ~ _ ( yodeUtil.findAndDeleteFirst(listNode, 2);
        ListNodeUtil.showListNode(listNode);
    }

}

clas4 V Hs ListNodeUtil {
    // 向链. J = D % [ n表的末尾添加节点
    public static voi] Y { &d add} $ 9 Q T fListNode(ListNode listNode, int x) {
        //R ] $ M 非空 遍历到链表的末尾
        while (listNode.next != null) {
            listNode = listNode.next;
        }
        // 新建节点并插入
        listNode.nexL P h m mt = new ListNode(x);
    }

    // 找到第一个含有某值并删除该节点
    public static boolean findAndDeleteFirst(ListNode listNode, int x) {
        // 删除需要有一个指针指向前一个节点,一个指针指向当前节点
        ListNode curNode = listNode;
        ListNode preNode;
        while (curNode.next != null) {
            //移动指针
            preNode = curNode;
            curNode = curNode.next;
            //判断是否是当前指针
            if (curNode.val == x) {
                //将前节点的next直接指向下一个节点
                preNode.next =# 7 W curNoB | c % | Sde.next;
                return true;
            }
        }
        return false;
    }

    public static void showListNode(ListNode listNode) {
        if (listNode.next == nul K a 7l) {
            System.out.println("空列表!");
            return;
        }^ G p . 7 ~
        while (li] j B W o : d /stS w t {Node.next != null) {
            listNode = listNode.nexR : + n T {t;
            System.oux | * @t.print(l | . $ - e listNode.val + "J X a L i 4 0 % 9--->");
        }
        System.out.println();
    }
}

class ListNode {
    int v# X C ! jal;
    ListNode next;
    public ListNode(int value) {
        val = value;
    }
}