单链表的反转
单链表的反转
单链表概念引入
有一个空的head节点作为头节点,头节点的存在主要是为了操作的统一性而设立的(删除增添节点等操作能够统一,不需要特殊考虑单独情况),当然它不是必须的,它的数据域毫无意义。
我们的目标:实现单链表的反转
1.如果考虑不破化原有链表,实现单链表翻转。这个实现比较简单,主要考虑在复杂度上,如果每次都取最后一个元素再插入新的链表,那么每次都要从头开始遍历一遍,复杂度为O(),但是我们可以考虑循环一遍将元素放入栈中,然后弹出实现反转。
2.在原有结构上实现反转。
最理想的方法当然是遍历过去一遍实现,要怎么办?
思路:
如果只有只有一个元素,不用操作;
如果多于一个元素,我们考虑到如果直接让后一个元素的next域指向前一个元素,那么再后一个元素的位置我们就无法确定,所以在将后一个元素的next指向前一个元素之前,我们将原本的next的指向元素保存就可以了。
看示例图:
我们借助两个移动的游标来完成工作,每次要改变 cursor2.next 的方向前,我们先用tmp保存好原来的cursor2.next指向的元素。
这样当cursor2.next完成赋值后:
我们记录了tmp的位置,之后两个cursor同时移动:
重复操作:
通过这个方法,我们就可以实现两个cursor的移动,实现迭代。
最后当tmp为空,循环截止;
实现代码:
public void reverse(){
if(size==1) return ;
int count=0;
Node cursor1=root.next;
Node cursor2=cursor1.next;
while(cursor2.next!=null){
Node tmp=cursor2.next;
cursor2.next=cursor1;
if(count==0){
cursor1.next=null;
count++;
}
cursor1=cursor2;
cursor2=tmp;
}
cursor2.next=cursor1;
root.next=cursor2;
}
测试代码:
Node结点类:
public class Node {
public Node next;
public int data;
public Node(){
next=null;
}
public Node(int data){
this.data=data;
this.next=null;
}
}
链表实现:
public class LinkedList {
private int size;
private Node tail;
private Node root;
public LinkedList(){
this.size=0;
tail=root=new Node();
}
public void append(int data){
tail=tail.next=new Node(data);
size++;
return ;
}
public void insert(int data,int index){
if(index<0 || index >size-1){
System.out.println("index错误");
return ;
}
Node cursor=root;
for(int i=0;i<index;i++){
cursor=cursor.next;
}
Node tmp=new Node(data);
tmp.next = cursor.next;
cursor.next=tmp;
size++;
}
public void traverse(){
Node cursor=root.next;
while(cursor!=null){
System.out.print(cursor.data+" ");
cursor=cursor.next;
}
System.out.println();
}
public void remove(int index){
if(index<0 || index >size-1){
System.out.println("index错误");
return ;
}
Node cursor=root;
for(int i=0;i<index;i++){
cursor=cursor.next;
}
cursor.next=cursor.next.next;
size--;
}
public void reverse(){
if(size==1) return ;
int count=0;
Node cursor1=root.next;
Node cursor2=cursor1.next;
while(cursor2.next!=null){
Node tmp=cursor2.next;
cursor2.next=cursor1;
if(count==0){
cursor1.next=null;
count++;
}
cursor1=cursor2;
cursor2=tmp;
}
cursor2.next=cursor1;
root.next=cursor2;
}
}
测试代码:
public class Main {
public static void main(String[] args){
LinkedList ll=new LinkedList();
for(int i=0;i<10;i++){
ll.append(i); //给链表添加元素
}
ll.traverse(); // 遍历输出链表内容
ll.reverse(); //链表反转
ll.traverse();
}
}