04_链表
01_概念
02_单向链表
03_单向循环链表
04_双向链表
05_单向链表Java代码实现
package DataStructureReview; import java.util.Stack; public class SingleLinkedListDemo { public static void main(String[] args) { //创建链表对象 SingleLinkedList list = new SingleLinkedList(); //创建节点数据 HeroNode node1 = new HeroNode(0, "刘备", "刘玄德"); HeroNode node2 = new HeroNode(1, "关羽", "关云长"); HeroNode node3 = new HeroNode(2, "张飞", "张翼德"); //add方法 list.add(node1); list.add(node2); list.add(node3); //遍历链表 list.printList(); System.out.println("=====根据no删除节点======"); System.out.println("删除对象为: " + list.delete(2)); System.out.println("=====根据no删除节点后======"); list.printList(); System.out.println("=====根据no修改节点======"); System.out.println("是否修改成功: " + list.update(new HeroNode(10, "曹操", "曹孟德"))); System.out.println("=====根据no修改节点后======"); list.printList(); System.out.println("=====根据no正序添加节点======"); list.addOrderBy(new HeroNode(5, "蒋介石", "中正")); list.addOrderBy(new HeroNode(3, "张作霖", "雨亭")); list.addOrderBy(new HeroNode(2, "秦琼", "叔宝")); System.out.println("=====根据no正序添加节点后======"); list.printList(); System.out.println("=====获取当前链表有效节点数======"); System.out.printf("当前链表有效节点数为:%d \n", list.size()); System.out.println("=====获取当前链表中倒数第K个节点数据======"); System.out.println(list.getNodeByK(2)); System.out.println("=====将当前链表反转,反转前======"); list.printList(); System.out.println("=====将当前链表反转,反转后======"); list.reverSetList(); list.printList(); list.reverSetList(); System.out.println("=====将当前链表反向遍历======"); list.printByStack(); System.out.println("=====链表合并前======"); list.printList(); System.out.println("=====链表合并后======"); SingleLinkedList newlist = new SingleLinkedList(); newlist.addOrderBy(new HeroNode(5, "汤二虎", "汤玉麟")); newlist.addOrderBy(new HeroNode(4, "汤二虎", "汤玉麟")); newlist.addOrderBy(new HeroNode(6, "鬼切", "刀鸣散华")); list.mergeList(newlist); list.printList(); } } //单向链表类 class SingleLinkedList { //设置链表head节点 private HeroNode head = new HeroNode(0, "", ""); //add方法,在链表尾部添加 public void add(HeroNode node) { //判断是否为空链表 if (head.next == null) { head.next = node; return; } //遍历链表 HeroNode temp = head.next;//辅助指针 while (true) { if (temp.next == null) { temp.next = node; break; } temp = temp.next; } } //addOrderBy,根据数据节点no添加,排序添加 public void addOrderBy(HeroNode node) { //判断是否为空链表 if (head.next == null) { head.next = node; return; } //遍历链表 HeroNode temp = head;//辅助指针 boolean flag = false; while (true) { if (temp.next == null) { break; } if (node.no < temp.next.no) { flag = true; break; } if (node.no == temp.next.no) { throw new RuntimeException("编号为:" + node.no + " 的数据节点已存在!"); } temp = temp.next; } //根据辅助指针找到插入的数据节点 if (flag) { node.next = temp.next; temp.next = node; } else { temp.next = node; } } //delete方法,根据no删除节点 public HeroNode delete(int no) { //判断是否为空链表 if (head.next == null) { throw new RuntimeException("当前链表为空,无节点可删除"); } //遍历链表 HeroNode temp = head;//辅助指针 boolean flag = false; while (true) { if (temp.next == null) { break; } if (temp.next.no == no) { flag = true; break; } temp = temp.next; } //根据辅助指针找到要删除的节点,和它前一个节点 //x:要删除的节点 y:要删除的前一个节点 z:要删除的后一个节点 //y.next = z HeroNode result = temp.next; if (flag) { temp.next = temp.next.next; } else { System.out.printf("此链表中没有找到编号为:%d 的节点\n", no); } return result; } //update方法,根据no删除节点 public boolean update(HeroNode node) { //判断是否为空链表 if (head.next == null) { throw new RuntimeException("当前链表为空,无节点可修改"); } //遍历链表 HeroNode temp = head.next;//辅助指针 boolean flag = false; while (true) { if (temp.no == node.no) { flag = true; break; } if (temp.next == null) { break; } temp = temp.next; } //根据辅助指针找到要修改的节点数据 if (flag) { temp.name = node.name; temp.nickname = node.nickname; } else { System.out.printf("此链表中没有找到编号为:%d 的节点\n", node.no); } return flag; } //遍历链表 public void printList() { //判断是否为空链表 if (head.next == null) { System.out.println("当前链表为空!"); return; } //遍历链表 HeroNode temp = head.next;//辅助指针 while (true) { System.out.println(temp); if (temp.next == null) { break; } temp = temp.next; } } //获取当前链表的有效节点数 public int size() { //判断是否为空链表 if (head.next == null) { return 0; } //遍历链表 HeroNode temp = head.next;//辅助指针 int sum = 0; while (true) { sum++; if (temp.next == null) { break; } temp = temp.next; } return sum; } //查找单链表中倒数第K个数据节点 public HeroNode getNodeByK(int k) { //判断是否为空链表 if (head.next == null) { System.out.println("当前链表为空!"); return null; } //由于链表只能从head开始遍历,我们可以将倒数变正数 //即倒数第K = size+1-k int size = size(); if (k > size || k <= 0) { throw new RuntimeException("倒数第" + k + "节点不存在!"); } HeroNode temp = head.next; for (int i = 1; i < size + 1 - k; i++) { temp = temp.next; } return temp; } //将当前链表反转 /*思路1:定义个节点变量x,当前链表为list:y1-y2-y3 * 从list中取出节点,依次添加到变量x后面: * x-y1 * x-y2-y1 * x-y3-y2-y1*/ public void reverSetList() { //链表为空或者节点数为1时,反转后为他本身 if (head.next == null || head.next.next == null) { return; } HeroNode head1 = new HeroNode(0, "", ""); HeroNode temp = head.next; HeroNode cur; //遍历链表 while (true) { cur = temp.next; temp.next = head1.next; head1.next = temp; if (cur == null) { break; } temp = cur; } head = head1; } //反向遍历链表,要求:使用stack public void printByStack() { Stack stack = new Stack(); //判断是否为空链表 if (head.next == null) { System.out.println("当前链表为空!"); return; } //遍历链表 HeroNode temp = head.next;//辅助指针 while (true) { stack.push(temp); if (temp.next == null) { break; } temp = temp.next; } int sum = stack.size(); for (int i = 0; i < sum; i++) { System.out.println(stack.pop()); } } //将两个有序单链表合并,合并之后需要依然有序 public void mergeList(SingleLinkedList newlist) { HeroNode newhead = newlist.head; //空链表判断 if (head.next == null) { head = newhead; return; } else if (newhead.next == null) { return; } //遍历newlist HeroNode temp = newhead.next; HeroNode cur; while (true) { cur = temp.next; try { addOrderBy(temp); } catch (RuntimeException e) { System.out.printf("编号为 %d节点已经存在!\n",temp.no); } if (cur == null) { break; } temp = cur; } } } //数据节点类 class HeroNode { public int no; public String name; public String nickname; public HeroNode next; public HeroNode(int no, String name, String nickname) { this.no = no; this.name = name; this.nickname = nickname; } @Override public String toString() { return "HeroNode{" + "no=" + no + ", name='" + name + '\'' + ", nickname='" + nickname + '\'' + '}'; } }
06_双向链表Java代码实现
package DataStructureReview; public class DoubleLinkedListDemo { public static void main(String[] args) { //创建链表对象 DoubleLinkedList list = new DoubleLinkedList(); //创建节点数据 Data node1 = new Data(0, "刘备"); Data node2 = new Data(1, "关羽"); Data node3 = new Data(2, "张飞"); //add方法 list.add(node1); list.add(node2); list.add(node3); //遍历链表 list.printList(); System.out.println("=====根据no删除节点======"); System.out.println("删除对象为: " + list.delete(2)); System.out.println("=====根据no删除节点后======"); list.printList(); System.out.println("=====根据no修改节点======"); System.out.println("是否修改成功: " + list.update(new Data(0, "曹操"))); System.out.println("=====根据no修改节点后======"); list.printList(); System.out.println("=====根据no正序添加节点======"); list.printList(); list.addOrderBy(new Data(5, "蒋介石")); list.addOrderBy(new Data(3, "张作霖")); list.addOrderBy(new Data(2, "秦琼")); System.out.println("=====根据no正序添加节点后======"); list.printList(); System.out.println("=====根据no删除节点======"); list.printList(); System.out.println("删除对象为: " + list.delete(5)); System.out.println("=====根据no删除节点后======"); list.printList(); } } class DoubleLinkedList { //设置head节点,pre为null,next指向第一个节点 public Data head = new Data(0, ""); //add方法,无序添加(在尾部添加) public void add(Data node) { //空链表判断 if (head.next == null) { head.next = node; node.pre = head; return; } //遍历链表 Data temp = head.next; while (true) { if (temp.next == null) { break; } temp = temp.next; } temp.next = node; node.pre = temp; } //addOrderBy,顺序添加(根据Data的no大小顺序) public void addOrderBy(Data node) { //判断是否为空链表 if (head.next == null) { head.next = node; node.pre = head; return; } //遍历链表 Data temp = head.next;//辅助指针 boolean flag = false; while (true) { if (node.no < temp.no) { flag = true; break; } if (node.no == temp.no) { throw new RuntimeException("编号为:" + node.no + " 的数据节点已存在!"); } if (temp.next == null) { break; } temp = temp.next; } //根据辅助指针找到插入的数据节点 if (flag) { node.pre = temp.pre; node.next = temp; temp.pre.next = node; temp.pre = node; } else { temp.next = node; node.pre = temp; } } //delete,根据Data的no删除节点,双向链表,可实现自我删除 public Data delete(int no) { //空链表判断 if (head.next == null) { throw new RuntimeException("当前链表为空,无节点可删除!"); } //遍历链表 Data temp = head.next; boolean flag = false; while (true) { if (temp.no == no) { flag = true; break; } if (temp.next == null) { break; } temp = temp.next; } if (flag) { //自我删除 temp.pre.next = temp.next; if(temp.next != null){ temp.next.pre = temp.pre; } return temp; } else { throw new RuntimeException("当前链表中没有编号为 " + no + "的数据节点!"); } } //update,根据Data的no更新节点 public boolean update(Data node) { //判断是否为空链表 if (head.next == null) { throw new RuntimeException("当前链表为空,无节点可修改"); } //遍历链表 Data temp = head.next;//辅助指针 boolean flag = false; while (true) { if (temp.no == node.no) { flag = true; break; } if (temp.next == null) { break; } temp = temp.next; } //根据辅助指针找到要修改的节点数据 if (flag) { temp.name = node.name; } else { System.out.printf("此链表中没有找到编号为:%d 的节点\n", node.no); } return flag; } //printList,遍历链表 public void printList() { //空链表判断 if (head.next == null) { System.out.println("当前链表为空!"); return; } //遍历链表 Data temp = head.next; while (true) { System.out.println(temp); if (temp.next == null) { break; } temp = temp.next; } } } class Data { public int no; public String name; public Data pre; public Data next; public Data(int no, String name) { this.no = no; this.name = name; } @Override public String toString() { return "Data{" + "no=" + no + ", name='" + name + '\'' + '}'; } }
07_单向环形链表Java代码实现(解决约瑟夫问题)
package DataStructureReview; public class CircleSingleLinkedDemo { public static void main(String[] args) { //创建环形链表对象 CircleSingleLinked list = new CircleSingleLinked(); list.add(new Person(1, "张有才")); list.add(new Person(2, "张作霖")); list.add(new Person(3, "张作福")); list.add(new Person(4, "张作相")); list.add(new Person(5, "张学良")); list.add(new Person(6, "张学民")); list.add(new Person(7, "张学诚")); list.add(new Person(8, "张首芳")); list.add(new Person(9, "张冠英")); //遍历list list.printList(); System.out.println("=========约瑟夫问题=========="); UtilList.josephuArr(list, 4, 3); } } class CircleSingleLinked { //设置head节点 public Person head; //add方法,无序添加(尾部添加) public void add(Person node) { //空链表判断 if (head == null) { head = node; node.next = node; return; } //遍历链表 Person temp = head; while (true) { if (temp.next == head) { break; } temp = temp.next; } temp.next = node; node.next = head; } //delete方法,根据Person.num删除 public Person delete(int num) { //空链表判断 if (head == null) { throw new RuntimeException("当前链表为空!"); } //遍历链表,获取到被删除元素的前一个元素 Person temp = head; boolean flag = false; while (true) { if (temp.next.num == num) { flag = true; break; } if (temp.next == head) { break; } temp = temp.next; } Person cur = temp.next; if (flag) { //只有一个元素时,需要置空head指针 if (temp.next == temp) { head = null; } else { //删除第一元素时,需要移动head指针 if(temp.next == head){ head = temp.next.next; } temp.next = temp.next.next; } } else { throw new RuntimeException("并未找到编号为:" + num + "的数据节点"); } return cur; } //printList方法 public void printList() { //空链表判断 if (head == null) { System.out.println("当前链表为空!"); return; } //遍历链表 Person temp = head; while (true) { System.out.println(temp); if (temp.next == head) { break; } temp = temp.next; } } } class UtilList { /** * @param list * @param startNo 指定从哪个per.num = k 的对象数数 * @param countNum 数几下(m),countNum>=1 */ public static void josephuArr(CircleSingleLinked list, int startNo, int countNum) { //判断编号是否在链表内 //空链表判断 if (list.head == null) { System.out.println("当前链表为空!"); return; } //遍历链表 Person temp = list.head; boolean flag = false; while (true) { if (temp.num == startNo) { flag = true; break; } if (temp.next == list.head) { break; } temp = temp.next; } if (flag != true) { System.out.println("当前链表并未找到编号为:" + startNo + "的对象!"); return; } while (true) { //遍历链表 Person cur = temp; for (int i = 0; i < countNum - 1; i++) { cur = cur.next; } int num = cur.num; temp = cur.next; System.out.println(list.delete(num)); if (list.head == null) { break; } } } } class Person { public int num; public String name; public Person next; public Person(int num, String name) { this.num = num; this.name = name; } @Override public String toString() { return "Person{" + "num=" + num + ", name='" + name + '\'' + '}'; } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· 字符编码:从基础到乱码解决
· SpringCloud带你走进微服务的世界