C语言实现单链表反转(图文)
据说是一道微软的面试题改编 挺有名的,据说很多人面试时 被要求当场纸写程序基本上都没答出来或者没答完整
本着他人故事不要成为我的事故的原则 ,尝试解一解 把思路分享一下( ̄▽ ̄)"
要完成链表的反转,则需要把后一个节点的指针指向前一个
需要三个指针 p,q,tmp 其中p q用来反转两个节点 tmp用来记住下一个要处理的节点
需要考虑的情况 大体有二 1.从头开始反转 2.从中间任意位置开始反转 当然,还有必不可少的边界检查
中间任意位置开始反序
从最最普遍的情况说起 从中间任意位置反序 大体需要三步 打开冰箱,塞进大象,关上冰箱门
1.预备工作 找到并记录节点
找到想要反转的下标为n的指针 用指针memory记录下它前一个的节点(n-1)的地址 下标为n n+1 n+2的节点位置分别用p.q.temp记录
2.完成对k个节点反序 (核心操作)
q->next 指向 p 即完成了一次反转 改变了两个节点
而后改变p.q.temp的值 使其指向的节点对应往后移一位 (注意操作的顺序,此时p->next不再指向q 而是指向其上一个节点)
重复这个动作k-1次 就完成了对k个节点的反序
改变指针 ↑
移动指针 ↑
k-1次操作后 如上图
3.和原有单链表相对接 (很重要,不要内存泄漏)
memory指向的下标为n-1节点 不能再指向下标为n的节点 而需要指向现在的p指向的节点(下标为n+k-1)
下标为n的节点不能再指向下表为n+1的节点 而要指向q指向的节点(下标为n+k)
这一部分的代码为
NODE *p,*q,*tmp,*memory;
p=head;
memory=head;
for(int i=0; i<n-1; i++)
{
memory=memory->next;
}
p=memory->next;
q=p->next;
tmp=q->next; //找到并标记节点
for(int i=0; i<k-1; i++)
{
q->next=p;
p=q;
q=tmp;
tmp=tmp->next;
} //完成k-1次反序操作 此时已有k个节点反序
memory->next->next = q;
memory->next=p;
return head; //对接 返回头指针
从头开始反序
可以参考上一种情况 甚至还要简单一些 不涉及对memory指针操作
有些做法需要额外添加一个空的头节点,我觉得没有必要 (可能是因为我写的是函数 这个时候把p作为头节点返回就行)
照例,源码和图 贴上
else if(n==0)