单链表反转
如何反转单链表?
定义链表
链表基础类,node
/**
* 链表节点
*
* @author zab
* @date 2022/5/19 22:54
*/
public class Node {
public Object data;
public Node next;
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
public Node getNext() {
return next;
}
public void setNext(Node next) {
this.next = next;
}
}
实现增删查的链表类
package zab.datastructures.list.single;
/**
* 单链表
*
* @author zab
* @date 2022/5/19 22:52
*/
public class SingleLinkedList<E> {
private int size = 0;
private Node firstNode = null;
public Node getFirstNode() {
return firstNode;
}
public void setFirstNode(Node firstNode) {
this.firstNode = firstNode;
}
/**
* 往单链表添加数据
*
* @author zab
* @date 2022/5/29 22:39
* @param e 链表元素
* @return true 成功
*/
public boolean add(E e) {
//第一个节点的情况
if (firstNode == null) {
firstNode = new Node();
firstNode.setData(e);
size++;
return true;
}
//非第一个节点
//构建节点
Node newNode = this.buildNode(e);
if (size == 1) {
firstNode.setNext(newNode);
size++;
return true;
}
Node node = firstNode.getNext();
//遍历到最后一个节点,给最后一个节点设置next
while (true) {
if (node.getNext() == null) {
node.setNext(newNode);
break;
}
node = node.getNext();
}
size++;
return true;
}
private Node buildNode(E e) {
Node node = new Node();
node.setData(e);
node.setNext(null);
return node;
}
/**
* 按照index获取元素
*
* @author zab
* @date 2022/5/29 22:39
* @param index 下标
* @return Node 元素结点
*/
public Node get(int index) {
if (index < 0) {
return null;
}
if (index == 0 && firstNode != null) {
return firstNode;
}
Node temp = firstNode;
int flag = 0;
//从头开始遍历,记录遍历下标
while (temp != null) {
if (flag == index) {
return temp;
}
flag++;
temp = temp.getNext();
}
return null;
}
/**
* 删除指定元素
*
* @author zab
* @date 2022/5/29 22:50
* @param e 要删除的节点
* @return true删除成功
*/
public boolean remove(E e) {
Node node = firstNode;
//前驱节点
Node preNode = null;
//遍历找值一样的,并且记录前驱节点
while (node != null && node.getData() != e) {
preNode = node;
node = node.getNext();
}
//循环完毕,有可能没找到,找到了node就有值,没找到,node就是最后一个节点的next(null)
//node !=null 就是找到节点了,需要执行删除操作
if (node != null) {
//preNode是空,表示找到的节点是头结点
if (preNode == null) {
firstNode = node.getNext();
} else {
//非头结点
preNode.setNext(node.getNext());
}
size--;
return true;
}
return false;
}
public int getSize(){
return size;
}
}
借助栈实现反转
都说反转链表很难?不考虑时间空间复杂度,我们尝试一种最简单的方式,看图:
我们有一个链表,然后遍历链表,把链表第0个放到栈底,把最后一个元素放到栈顶,最后根据栈的先进后出,把原先链表中的最后一个元素取出,添加新链表,作为第一个元素,以此类推,实现链表反转。
代码如下:
/**
* 用外力,栈
*/
public static SingleLinkedList inverseList1(SingleLinkedList list) {
Stack<Node> stack = new Stack<>();
Node node = list.get(0);
if (node == null || list.getSize() == 1) {
return list;
}
while (node != null) {
stack.push(node);
node = node.getNext();
}
SingleLinkedList result = new SingleLinkedList();
while (!stack.isEmpty()) {
Node pop = stack.pop();
result.add(pop.getData());
}
return result;
}
利用多指针
多指针思路如下图
如图所示,有三个指针begin、middle、end。最开始begin指向null,middle指向链表第一个元素,end指向第二个元素。遍历链表,直到end指向链表的最后一个元素的next(肯定为null)为止,遍历链表时,只需要做一件事,就是把middle的next指向begin,实现链表的反转。
代码如下:
/**
* 三指针法,用三个指针记录
*/
public static SingleLinkedList inverseList2(SingleLinkedList list) {
Node head = list.getFirstNode();
if (head == null || head.getNext() == null) {
return list;
}
Node begin = null;
Node middle = head;
Node end = head.getNext();
while (true) {
middle.setNext(begin);
begin = middle;
middle = end;
end = end.getNext();
if (end == null) {
break;
}
}
middle.setNext(begin);
head = middle;
list.setFirstNode(head);
return list;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构