算法持续更新

 链表指针(一定要看完)

我想了两年,终于彻底的理解了指针,现在我将毫不保留的传授给你们,因为只有我懂你O(∩_∩)O。 绝对让你对指针有了进一步的认知。

无敌重点:  结点存放的仅仅只是地址。

假如  第一个节点是 ListNode head

然后 ListNode  p  =head 

假如,我现在 让head = null;

你是不是以为第一个节点变成null了。 错。    第一个节点完好无损 

P并没有受到了改变,  变量head只是存放了第一个节点的地址而已。

你可能会疑问,   一开始    head.val = 5 ,第一个节点的值确实会变成5 

head.next =  某个节点,   那么  head.next确实存放的是某个节点。

但是他仅仅可以操作他而已。你第一个节点的地址不管怎么弄,都是不会变的,内存已经生成好定在那了。 所以 head = null; 仅仅是把  head 变成了null 而已。 那个地址代表的节点完好无损。

所以在head= null  前,我们定义了 ListNode  p  =head   。 即使你Head =  null  ,但是我们p已经存放了那个节点的地址啊,我们还是可以找到那个节点,他还是好好的。

我就拿题目来讲吧。(可能有点啰嗦,但是我相信你经过上面的话后,已经有点觉悟了。下面我就继续啰嗦。)

题目叫:  反转链表

首先我们来认识指针的结构。  java中指针就是一个类。c++应该是结构体。拿java来说。

他就是有两个属性  : 一个是int类型。这个大家都理解。 主要难理解的就是 next,其实理解了也很简单。

类名字和属性名字 可以随便取,但是题目定义了你就得用他的。

public class ListNode {      
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
 }

 下面开始讲解

next ,其实就是一个指针类型也是ListNode 有点像套娃懂吧(牢记)

超级重点:  指针存储的是地址,地址,地址

下面为了方便,我拿一下题目解答的图片来讲解(牛客拿的,我不知道怎么去掉我的水印)

题目给定了一个头节点 head ,他代表图片第一个结点,也就是存有  数据为1 的那个结点。

那么  说明    head.val  = 1   (我就按照上面定义的指针 , val代表存放的是数据, next代表存放的是下一个结点地址)   因为head其实也是一个类,所以   head. 属性(head.val)  这是java基础,我就不说这么多了  ,反正就是   类. 属性   

然后 head.next 代表的就是 第二个节点的地址(其实也就是第二个节点) 

下面我们来认识这句话,

head =head.next  

这代码的意思就是, 把head的next指向的地址,赋值给head。 重点:那么此时head存放的就是head.next(也就是第二个结点)的地址了。

所以head就变成了 第二个结点(也就是存有数据为2的那个节点)

 //  head即为给定的头结点,即第一个节点(他就是一个节点而已。只是他的next存放了下一个结点的地址,而他下一个结点又存放了下下一个结点的地址,然后把他们连了起来。)

这里我额外演示一下,链表插入的过程。
这里我要把一个名为p的节点插入到L的结点的后面。

根据我前面的讲解,相信你已经有一丝丝的觉悟了,那么接下来,你就做好真正的觉悟吧!

这里我把L右边的那个节点叫做 M 结点,方便说明(注意是L右边那个,不是要插入的p节点)

第一步:    p.next = L.next;    

L.next 本来存放的是 下一个结点(M)的地址(也就是L的右边那个节点M,看图片) 。

  p是要插入的结点, 没插入之前,  p.next指向的是null,你可以理解为,  他什么都没指向,就单一 一个结点。 

现在我们要把p插入到L和M的之间,那么我们是不是就要 拿到 M结点, 然后 p.next指向 M,就跟图片蓝色字体画的那样去做。

M节点 其实就是 L.next  即 L.next  ==  M

所以根据蓝色字体的做法,其实就是  P.next =  L.next

第二步:      L.next = p ;   

然后我们去完成绿色字体的步骤。

这个时候 L.next 存放(指向)的还是 M的地址,而我们需要把 L.next指向节点P(即存放P的字地址)

所以 L.next = p

这样,我们就完成了一个节点的插入。

在这里插入图片描述

是不是有头绪了,下面我们来讲上面说的那道  反转链表的题目,边看图片边看代码,

边看我注释,代码我里面写了注释。

下面的代码我就只描述图片的第一步和第二步,不然文字描述太难了。

注意, head.next在右边和在左边的含义。

head.next在右边的意义是,把head指向的下一个结点赋值给左边的结点

此时 temp 存放的是 head.next指向的结点的地址。
        ListNode temp = head.next;

而head.next在左边的意义是, 让head的next 指向(存放) 右边的节点(即重新指向)

此时 head.next存放(指向)的是 newHead这个节点的地址
        
        //让head的next指向 新链表节点。注意 
        head.next = newHead;

    

不知道,到这里,你头脑清晰一点,如果没有,可能还是我写的有点绕吧。继续看完下面的代码,就是反转链表那道题的题解。

无敌重点:  结点存放的仅仅只是地址。

假如  第一个节点是 ListNode head

然后 ListNode  p  =head 

假如,我现在 让head = null;

你是不是以为第一个节点变成null了。 错。    第一个节点完好无损 

P并没有受到了改变,  变量head只是存放了第一个节点的地址而已。

你可能会疑问,   一开始    head.val = 5 ,第一个节点的值确实会变成5 

head.next =  某个节点,   那么  head.next确实存放的是某个节点。

但是他仅仅可以操作他而已。你第一个节点的地址不管怎么弄,都是不会变的,内存已经生成好定在那了。 所以 head = null; 仅仅是把  head 变成了null 而已。 那个地址代表的节点完好无损。

所以在head= null  前,我们定义了 ListNode  p  =head   。 即使你Head =  null  ,但是我们p已经存放了那个节点的地址啊,我们还是可以找到那个节点,他还是好好的。

现在,我相信你是不是觉悟了,觉悟了就开始看下面题目答案的代码吧!

/*  题目给的链表的结构
public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}*/


public ListNode ReverseList(ListNode head) {
    //  head即为给定的头结点,即第一个节点(他就是一个节点而已。只是他的next存放了下一个结点的地址,而他下一个结点又存放了下下一个结点的地址,然后把他们连了起来。)

    // 定义一个节点, 代表图片中的新链表的第一个节点
    ListNode newHead = null;
    while (head != null) {

        //保存原链表中头节点的下一个节点(地址)。
        ListNode temp = head.next;
        
        //让head的next指向 新链表节点。(重新指向地址, 即指向那个null的地址)
        head.next = newHead;

        //更新新链表 (让newHead 存放的地址变成head存放的地址)
        newHead = head;

        // 把头结点的下一个地址赋值给 head (此时head的地址是原链表的第二个节点)
        head = temp;
    }
    //返回新链表(他只代表一个节点而已,关系是通过指针next连接起来的)
    return newHead;
}

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值