循环方式
在不使用额外存储节点的情况下使一个单链表的所有节点逆序?我们先用迭代循环的思想来分析这个问题,链表的初始状态如下
初始状态,prev是NULL,head指向当前的头节点A,next指向A节点的下一个节点B。首先从A节点开始逆序,将A节点的next指针指向prev,因为prev的当前值是NULL,所以A节点就从链表中脱离出来了,然后移动head和next指针,使它们分别指向B节点和B的下一个节点C(因为当前的next已经指向B节点了,因此修改A节点的next指针不会导致链表丢失)。
操作步骤:
next = head->next;
head->next = prev;
prev = head;
head = next;
进行新一轮的迭代。
head为null时,循环结束。
递归方式
递归的一般步骤:
生成子问题。
子问题需要与原问题是同样的事,且更加简单,即把N的问题化简为N-1。构造出口
不能无限制的调用,必须有个出口,化简为非递归情况处理。
将链表分为当前表头节点和其余节点,先将当前的表头节点从链表中拆出来,然后对剩余的节点进行逆序,最后将当前的表头节点连接到新链表的尾部。
这里边的关键点是头节点head的下一个节点head->next将是逆序后的新链表的尾节点,也就是说,被摘除的头接点head需要被连接到head->next才能完成整个链表的逆序。
代码
public class SingleLinkReverse {
//节点类
static class ListNode{
int data;
ListNode next;
public ListNode(int data){
this.data = data;
}
}
//循环方式
public static ListNode reverse(ListNode head){
if (head == null){
return null;
}
ListNode cur = head;
ListNode oldHead = null;
ListNode newHead = null;
while(cur != null){
oldHead = cur.next;
cur.next = newHead;
newHead = cur;
cur = oldHead;
}
return newHead;
}
//递归方式
public static ListNode reverseList(ListNode pHead){
if(pHead==null||pHead.next==null){
return pHead;
}
ListNode nowHead = reverseList(pHead.next);
//交换2个节点
// ListNode pNode =nowHead;
// while(pNode.next!=null){
// pNode=pNode.next;
// }
// pHead.next = pNode.next;
// pNode.next = pHead;
pHead.next.next=pHead;
pHead.next=null;
return nowHead;
}
public static void main(String[] args) {
// 测试
ListNode node1 = new ListNode(1);
ListNode node2 = new ListNode(2);
ListNode node3 = new ListNode(3);
ListNode node4 = new ListNode(4);
ListNode node5 = new ListNode(5);
node1.next = node2;
node2.next = node3;
node3.next = node4;
node4.next = node5;
ListNode head = new ListNode(0);
head = reverseList(node1);
while(head!=null){
System.out.println(head.data);
head = head.next;
}
}
}