结点的数据结构为
public class Node {
int data=0;
Node next=null;
public Node(int data){
this.data=data;
}
public Node(){}
}
单链表的数据结构为
public class ListNode {
private Node head = new Node();
}
链表为空的情况下只有一个单独的头结点
逆置过程:
由于不能开辟新的存储空间,所以只能给几个需要操作的结点改个新名字来使用
逆置思路:由于需要逆转顺序,所以不能从头结点直接取出后一个结点塞到链表末尾,而是每次将链表中初始末尾结点的前一个结点取出,并插入到链表末尾.
故而逆置过程为:声明一个尾结点“end”用来标记链表的“真”末尾位置(即不管链表如何改变,end始终为最末尾的结点),其次需要声明一个常结点"change"用来标记链表初始状态下的末尾结点.最后需要一个指针结点node,用于辅助查找确定需要被修改的位置.
声明完毕后,遍历链表,将链表的末尾地址分别赋值给尾结点"end"与常结点"change",由于遍历完成后指针结点的位置到了末尾,需要手动将其放到头结点位置.
开始进行逆置:
判断逆置是否结束的条件为:头结点的下一个结点即为常结点.
指针结点将作为一个"小链表"的头结点使用(当前"node"结点的下下个结点为常结点"change",此三个结点构成的小型链表),小链表中共三个结点,若小链表的末尾结点为常结点,则小链表中的第二个结点需要被修改.
具体操作为:在node.next.next==change的情况下
end.next=node.next(将end的next指针指向node结点的下一个结点)
end=end.next(end结点向后移动一位,确保用于处于链表的末尾)
node.next=change(将node结点的next指针指向常结点"change",抹掉原中间结点的位置,使其真正成为尾结点)
node=head(修改结束后将node重新放到头结点位置)
end.next=null;(让现end结点的指针指向空,防止出现循环嵌套)
public void turn(ListNode listNode){
Node node = listNode.head.next;
Node end = null; //定义尾结点
Node change = null; //定义常结点即链表初始状态的末尾结点
while(node!=null){
end = node;
node=node.next;
} //遍历整个链表,并定义出尾结点
change = end; //将尾结点地址给常结点
node=head; //指针结点重新回到头结点位置
while (head.next!=change){
if (node.next.next==change){
end.next=node.next;
end=end.next;
node.next=change;
node=head;
end.next=null;
}else {
node=node.next;
}
} //执行逆置操作
}