简介
链表反转是一种常用的操作。在JDK7的hashMap扩容中就是用到了头插法链表反转,本文主要是记录实现代码,有不理解其转换过程的请移步搜索,查看相关动画插图,帮助其理解。
代码实现
package com.pinet.rest.modular.controller.deductionCard;
/**
* @author Y2M
* @createTime 2021/8/4
* @comment
*/
public class Link {
static class Node {
private String name;
private Node next;
public Node(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setNext(Node next) {
this.next = next;
}
public Node getNext() {
return next;
}
@Override
public String toString() {
return "Node{" +
"name='" + name + ''' +
'}';
}
}
private Node root;
public void setRoot(Node root) {
this.root = root;
}
public Node getRoot() {
return root;
}
}
package com.pinet.rest.modular.controller.deductionCard;
import java.util.ArrayList;
import java.util.List;
/**
* @author Y2M
* @createTime 2021/8/4
* @comment
*/
public class Test {
private static Link link = new Link();
//链表初始化
static {
Link.Node node1 = new Link.Node("1");
Link.Node node2 = new Link.Node("2");
Link.Node node3 = new Link.Node("3");
Link.Node node4 = new Link.Node("4");
Link.Node node5 = new Link.Node("5");
node1.setNext(node2);
node2.setNext(node3);
node3.setNext(node4);
node4.setNext(node5);
link.setRoot(node1);
}
public static void main(String[] args) {
//链表翻转
flipFive(link);
//遍历
LinkSout(link);
}
//链表反转 方法一 使用额外空间
public static void flipOne(Link link){
if (link == null || link.getRoot().getNext() == null){
return;
}
List<Link.Node> nodeList = new ArrayList<>();
Link.Node node = link.getRoot();
while (node!=null){
nodeList.add(node);
node = node.getNext();
}
for (int i = nodeList.size()-1; i >= 0; i--) {
//设置头结点
if (i == nodeList.size() - 1){
link.setRoot(nodeList.get(i));
}
if (i != 0){
nodeList.get(i).setNext(nodeList.get(i-1));
}else {
nodeList.get(i).setNext(null);
}
}
}
//链表反转 方法二 迭代反转链表
public static void flipSec(Link link){
if (link == null || link.getRoot().getNext() == null){
return;
}
Link.Node beg = null;
Link.Node mid = link.getRoot();
Link.Node end = link.getRoot().getNext();
while (true){
mid.setNext(beg);
if (end == null){
break;
}
beg = mid;
mid = end;
end = end.getNext();
}
link.setRoot(mid);
}
//链表反转 方法三 递归反转链表
public static Link.Node flipThird(Link.Node node){
//递归出口
if (node == null || node.getNext() == null){
return node;
}
Link.Node cur = flipThird(node.getNext());
node.getNext().setNext(node);
node.setNext(null);
return cur;
}
//链表反转 方法四 头插法 JDK7 hashmap 扩容就是用的这种方法
public static void flipForth(Link link){
Link newLink = new Link();
while (link.getRoot() != null){
Link.Node rootRel = link.getRoot();
Link.Node next = rootRel.getNext();
Link.Node root = newLink.getRoot();
Link.Node linkRoot = link.getRoot();
linkRoot.setNext(root);
newLink.setRoot(linkRoot);
link.setRoot(next);
}
link.setRoot(newLink.getRoot());
}
//链表反转 方法五 就地内置法 和头插法思想一样 区别在于 头插法是新建一个链表实现的 而就地内置则是对原数据直接进行改造
public static void flipFive(Link link){
if (link.getRoot() == null || link.getRoot().getNext() == null){
return;
}
Link.Node beg = null;
Link.Node end = null;
beg = link.getRoot();
end = link.getRoot().getNext();
while (end!=null){
//把end从链表摘除
beg.setNext(end.getNext());
//将end移动至链表头
end.setNext(link.getRoot());
link.setRoot(end);
//调整 end 的指向,另其指向 beg 后的一个节点,为反转下一个节点做准备
end = beg.getNext();
}
}
public static void LinkSout(Link link){
Link.Node root = link.getRoot();
while (root!=null){
System.out.println(root.toString());
root = root.getNext();
}
}
}