前段时间有同事面试,给面试的人都提一个算法问题那就是单链表的反转,好多小伙伴都不会,或者表示一听算法就懵逼了,自己写了一个。就是5-4-6-8-9-1-2-7,反转输出7-2-1-9-8-6-4-5,我自己写的反转有两种方式。一种是递归,一种是遍历,也是很普通的两种方式。
<一>递归的方式
先看图
先解释一下一个Node有data和next,data是数据,next是指向下一个节点,相当于C中的指针了。我们先放3个数据,图中的1-3是一次完整的操作。
先想一哈这个怎么写,既然递归,而且是链表就要传入一个头结点,就是图中的A节点,递归中要判断,下一个节点的是不是空节点来,来决定要不要再次调用自己去处理数据。
具体的递归方法怎么写,看图里面的数据是如何处理的,
注意的3点;
1.判断是不是null节点,也就是找到最后一个节点,并且返回出来作为第一个节点
2.找到最后一个节点后,将最后一个节点的next指向自己,并将自己的next复制为null,将自己设置为最后一个节点
3.递归是重复调用自己的
这个是node节点
public class Node {
private int Data;
private Node Next;
public Node(int data) {
this.Data=data;
}
public int getData() {
return Data;
}
public void setData(int data) {
Data = data;
}
public Node getNext() {
return Next;
}
public void setNext(Node next) {
Next = next;
}
}
具体的递归方法看图的操作去写
public Node ergodic(Node heade){
//1.判断是不是null节点,也就是找到最后一个节点,并且返回出来作为第一个节点
if(heade==null||heade.next==null){
return heade;//判断是最后一个节点,直接将最后一个节点往上返回
}
//不断调用自己找见最后一个节点
Node result=ergodic(heade.getNext());
//2.找到最后一个节点后,将最后一个节点的next指向自己,并将自己的next复制为null,将自己
//设置为最后一个节点
heade.getNext().SetNext(heade);
heade.setNext(null);
return result;
}
具体的执行大概说一下调用ergodic
将A作为heade传入,判断是不是最后一个节点,
调用ergodic并传入A的next节点即B节点,判断B节点不是最后一个节点,调用ergodic传入B节点的next,即C节点,C节点是最后一个节点,returnC节点,result是C节点。此时的heade是B节点,将B节点的next节点的next设置为B节点,就是C节点next设置为B节点**,header现在还是B节点,将B节点的next设置为null,return了C节点,此时的result是刚才返回的C节点,heade是A节点,将A节点的next节点的next设置为A节点,即B节点的next设置为A节点,A节点的的next设置为null,返回C节点。
到此整个递归就走完了。返回的是C节点,即图中3的结果。c指向b,b指向a,反转结束了。
<一>遍历反转
就是将B节点next中的节点暂时记录,将A节点和B节点,的next重新设置,A节点的next设置为null,B节点的next设置为A节点,再进行下一轮的互换,C节点和B节点的next互换,C节点的Next指向B节点,
具体代码
public static Node ergodic(Node head) {
if (head == null) {
return head;
}
Node pre=head;//第一个节点
Node cur=head.getNext();//第二个节点
Node tmp;
while (cur!=null) {
tmp=cur.getNext();//第三个节点
cur.setNext(pre);//将第二个节点的指针指向第一个节点
//互换位置
pre=cur;//第二个节点成为前一个节点
cur=tmp;//第二个节点的下一个节点为第三个节点
}
head.setNext(null);
return pre;
}
整体的代码:
import com.sun.xml.internal.bind.util.Which;
public class Listflip {
public static void main(String[] args) {
Node heaedNode = new Node(0);
Node heaedNode1 = new Node(1);
Node heaedNode2 = new Node(2);
Node heaedNode3 = new Node(3);
Node heaedNode4 = new Node(4);
heaedNode.setNext(heaedNode1);
heaedNode1.setNext(heaedNode2);
heaedNode2.setNext(heaedNode3);
heaedNode3.setNext(heaedNode4);
// 递归反转前
Node node = heaedNode;
while (node != null) {
System.out.println(node.getData() + "");
node = node.getNext();
}
// 递归反转后
node = ergodic(heaedNode);
while (node != null) {
System.out.println(node.getData() + "");
node = node.getNext();
}
}
// 递归反转
public static Node reversel(Node head) {
if (head == null || head.getNext() == null) {
return head;
}
Node renode = reversel(head.getNext());
head.getNext().setNext(head);
head.setNext(null);
return renode;
}
// 遍历反转
public static Node ergodic(Node head) {
if (head == null) {
return head;
}
Node pre=head;//第一个节点
Node cur=head.getNext();//第二个节点
Node tmp;
while (cur!=null) {
tmp=cur.getNext();//第三个节点
cur.setNext(pre);//将第二个节点的指针指向第一个节点
//互换位置
pre=cur;//第二个节点成为前一个节点
cur=tmp;//第二个节点的下一个节点为第三个节点
}
head.setNext(null);
return pre;
}
}