1、反转一个单链表
解法:可以采用循环和递归两种方式解决,这里用循环实现
eg:如下有一个链表
反转之后:
分析:首先观察一下反转前后的链表,新的头变成了原链表的尾节点,这个过程也就是
指向由
变成了
可以发现出现变化的是:整个链表的头节点和next域,原链表中888节点的next域保存的是001节点的地址,反转后001节点的next域保存了888节点的地址值,不断重复这个操作,并且原头节点888的next域变成了null。
思路:首先定义一个变量cur遍历链表,并且这个cur始终指向当前要反转的这个节点,因为反转的过程就是让当前节点的next域指向他的前驱,所以我们需要再定义一个变量指向当前要反转节点的前驱,当这个cur要反转后,他的下一个节点就更新了,我们无从得知原链表中这个cur的下一个节点,所以,必须要再定义一个变量curNext来记录当前反转节点的下一节点。最后要考虑的就是遍历的终止条件和反转后链表的头的问题了。
详细步骤:
-
定义四个变量
cur (遍历链表,并且永远指向当前要反转的节点)
prev (反转后链表的临时的头,cur指向原链表头,此时还没有反转所以prev初始化为null)
newHead (从语义来看,新链表还没生成此时他的初始化值为null)
curNext (这个的定义一定首先考虑到他的出现可能会带来的空指针异常的问题) -
遍历链表,循环的条件就是(cur != null),为了防止curNext空指针异常,我们把他定义在循环里面,cur不为空,那么他的next就是curNext节点就不会出现空指针异常的情况。
cur在遍历中每走一个节点我们都要考虑到他是不是最后一个,如果是,那么当前节点就是新的头,将此时的cur置为newHead。 -
反转节点,此时不要忘记头节点也是要反转的,他反转之后就变成了尾节点,每次完成了一次反转后cur和prev都是要更新的(始终让cur指向当前要反转的节点,prev作为一个临时的头指向反转后的链表)
cur.next = prev;
prev = cur;
cur = curNext;
java源代码
public Node reverse() {
Node prev = null;
Node cur = this.head;
Node newHead = null;
while (cur != null) {
Node curNext = cur.next;
if (curNext == null) {
newHead = cur;
}
cur.next = prev;
prev = cur;
cur = curNext;
}
return newHead;