您的位置:首页 > 职场人生

剑指offer代码解析——面试题16反转单链表

2016-03-14 09:54 337 查看
本题的详细解析均在代码中注释:

/**
* 题目:将单链表反转,并输出反转后链表的头结点
* @author 大闲人柴毛毛
*/
public class RevertLink {
/**
* 分析:本题是要将链表“反转”,而不是反向输出,这点要特别注意。
* 反转需要改变链表的结构,使所有指针都指向相反方向;
* 而反向输出不需要改变链表结构,只需反向输出即可。
* 对于反向问题可使用栈来实现,可参见我的博客《剑指offer——面试题5》,这里不再赘述。
* 下面来解决反转问题。
*/

/**
* 反转单链表其实就是将链表中的指针指向相反方向,
* 若a1和a2是单链表中两个相邻的结点,未反转前的状态是:a1.next = a2,
* 现在进行反转:a2.next = a1.
* 此时,虽然a2指向了a1,但链表出现了“断裂”,a2和它的后继结点发生了断裂,无法继续进行反转操作。
* 因此,我们需要再增加一个指针a3,指向a2的后继结点。
* 当反转完a2结点后,从a3开始继续依次向后进行反转操作,直到整个链表反转完为止。
* 代码如下:
*/

/**
* 反转链表
* @param first 链表的头结点
* @return 返回反转后链表的头结点
*/
public static <T> Node<T> revertLink(Node<T> first){
//当链表为空时
if(first==null){
System.out.println("链表为空!");
return null;
}

//当链表只有一个结点时
if(first.next==null){
return first;
}

//当链表只有两个结点时
if(first.next.next==null){
//end为链表的尾结点,是反转后的头结点
Node<T> end = first.next;
//将第二个结点的next域指向第一个结点
first.next.next = first;
//将第一个结点的next域设置null
first.next = null;
return end;
}

//当链表有三个及以上结点时
{
Node<T> a1 = first;//a1指向头结点
Node<T> a2 = first.next;//a2指向第二个结点
Node<T> a3 = first.next.next;//a3指向第三个结点

//将头结点的后继设为null
first.next = null;

//不停的将a1->a2反转为a2->a1,直到a3为空
while(a3!=null){
//a2的后继设为a1
a2.next = a1;
//a1、a2、a3依次向后移一位
a1 = a2;
a2 = a3;
a3 = a3.next;
}

//将最后一个结点反向
a2.next = a1;
return a2;
}
//PS:这里使用局部代码块一方面增强了代码的可读性,另一方面使得局部代码块中的变量能够在代码块结束之后立即释放,从而节约了内存空间。
}
}

/**
* 定义结点
*/
class Node<T>{
public T data;
public Node<T> next;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: