链表逆置详细讲解(图文)

前言
链表逆置是初学时有困扰到我的难点.

由于链表头结点可放可不放数据,所以写代码时候 ->next 用的云里雾里。

这里讲解头结点与第一结点区分的情况,即头结点你把它看作这个 链表的“文件名” 就行。
若头结点为L,则第一结点为L->next。

代码
void listReverse(linkedList &L)
{
    node *p,*s;
    //1.
    p = L->next;
    L->next = NULL;
    
    while(p)
    {
        //2.1
        s = p; 
        p = p->next;
        //2.2
        s->next = L->next; 
        L->next = s;
    }
}

看不懂别慌。我会把代码拆解成三块为你讲解。
讲解前,先做一个理解工作,以 L->next 为例,按在表达式左边or右边分,存在两种情况:

情况一(左):L->next = NULL;

重点在next,即L的指针域,该表达式将指针域指向NULL。

情况二(右):p = L->next;

重点在 L->next 整体, 即 L->next 这个结点,->next在这里就是个形式,目的还是为了告诉你是这个结点!该表达式将p指针指向结点L->next。

讲解
我们先看第一轮循环做了什么:

建议阅读顺序:黑色(初始)、蓝色(操作)、红色(理解)
 

 

第二轮:
 
建议阅读顺序:黑色(初始)、蓝色(操作)、红色(理解)


第三轮省略(可以自己尝试)。
 
 

总结
不难发现:

链表逆置利用了s、p两个指针的移动实现

每一轮循环体执行结束后,s指向刚刚逆置成功的结点,p指向下一轮待逆置的结点

为什么需要p?
因为2.2步骤中s->next会被改写,
若只有s,会丢失剩余的结点,
这时候p起到暂存的作用,等待下一轮2.1步骤中的s=p找到它。

 
 

最后给一份带注释的代码~

void listReverse(linkedList &L)
{
    node *p,*s;
    //1.准备工作
    p = L->next;
    L->next = NULL;
    
    while(p)
    {
        //2.1 s记录正在处理的结点,p记录下一轮待处理的结点
        s = p;             //s承接上一轮记录的位置
        p = p->next;     //p为下一轮记录位置
        //2.2 把s插入 已逆置的部分 中
        s->next = L->next;  // L->next代表已逆置的第一结点,s的指针域指向它
        L->next = s;    //(头结点的指针域,即)第一结点 设置为s
        //2.2步骤相当于:
        //s 对 队伍(已逆置部分)的队首(已逆置的第一结点)说:你不要排在柜台前了,你排在我后面
        //等队伍排在s后面后,s自己排到了柜台前
    }
}
————————————————
版权声明:本文为CSDN博主「_像风一样」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_51366188/article/details/114111668

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值