双向链表
双向链表跟单链表类似,每个节点多了previous指针,指向前一个元素;还多了一个tail指针指向链表的尾节点;可以从头尾两个方向遍历链表。
代码实现

public class DoubleLinkedList { private DoubleNode head; private DoubleNode tail; private Integer size = 0; /** * 添加至链表头 * @param node */ public void addFirst(DoubleNode node) { if (head == null) { head = node; tail = node; } else { node.next = head; head.prev = node; head = node; } size++; } /** * 添加至链表尾 * @param node */ public void addLast(DoubleNode node) { if (tail == null) { head = node; tail = node; } else { tail.next = node; node.prev = tail; tail = node; } size++; } /** * 按照某属性的顺序添加 * @param node */ public void addByOrder(DoubleNode node) { // 第一个节点 if (head == null) { head = node; tail = node; size ++; return; } // 新节点比头节点小 if (node.no <= head.no) { node.next = head; head.prev = node; head = node; return; } //新节点比尾节点大 if (node.no >= tail.no) { node.prev = tail; tail.next = node; tail = node; return; } // 找到比新节点大的节点 DoubleNode tmpNode = head; while (tmpNode != null && tmpNode.no < node.no) { tmpNode = tmpNode.next; } node.prev = tmpNode.prev.next; tmpNode.prev.next = node; tmpNode.prev = node; node.next = tmpNode; size++; } /** * 修改 * @param node */ public void modify(DoubleNode node) { DoubleNode tmp = head; while(tmp !=null) { if (tmp.no.equals(node.no)) { tmp.name = node.name; break; } tmp = tmp.next; } } /** * 根据编号获取节点 * @param no * @return */ public DoubleNode query(int no) { DoubleNode tmp = head; while (tmp != null) { if (tmp.no.equals(no)) { return tmp; } tmp = tmp.next; } return null; } /** * 根据编号删除节点 * @param no */ public void remove(int no) { if (head == null) { return; } if (head == tail) { head = null; tail = null; return; } //头节点 if (no == head.no) { head.prev = null; head = head.next; size--; return; } // 尾节点 if (no == tail.no) { tail.prev.next = null; tail = tail.prev; size--; return; } // 非根节点 DoubleNode tmp = head.next; while (tmp != null) { if (no == tmp.no) { break; } tmp = tmp.next; } // 节点不存在 if (tmp == null) { return; } tmp.prev.next = tmp.next; tmp.next.prev = tmp.prev; size--; } /** * 打印 */ public void display() { if (head == null) { System.out.println("This DoubleLinkedList is null."); return; } DoubleNode tmp = head; while(tmp != null) { System.out.println(tmp.toString()); tmp = tmp.next; } } /** * 获取链表长度 * @return */ public Integer getSize() { return size; } }
节点

public class DoubleNode { protected Integer no; protected String name; protected DoubleNode next; protected DoubleNode prev; public DoubleNode(Integer no, String name) { this.no = no; this.name = name; } @Override public String toString() { return "DoubleNode[" + "no=" + no + ", name='" + name + '\'' + ']'; } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?