Java数据结构——循环链表
一、单向循环链表
表中的最后一个节点的指针域指向头结点,整个链表形成一个环。其他的与单链表相同。
(以下图片均来自网络,侵删)
插入操作
删除操作
简单实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 | public class CiNode { private Object data; private CiNode next; private static CiNode first; // 临时结点,头结点,并不是链表里想要的值,起到标记链表头的作用 public CiNode() { super (); } public CiNode(Object data, CiNode next) { super (); this .data = data; this .next = next; } public Object getData() { return data; } public void setData(Object data) { this .data = data; } public CiNode getNext() { return next; } public void setNext(CiNode next) { this .next = next; } public static void add(CiNode node, int index) { if (index == 0 ) { node.next = first.next; first.next = node; } else { int temp = 0 ; for (CiNode n = first.next;; n = n.next) { temp++; if (temp == index) { node.next = n.next; n.next = node; break ; } } } } public static void remove( int index) { if (index % 5 == 0 ) { // 删除第一个元素,考虑循环 first.next = first.next.next; } else { int temp = 0 ; for (CiNode n = first.next;; n = n.next) { if (n == first) { temp -= 1 ; // 减一是因为链表循环计数时会把first记一次,所以这里减一次,使下标一致 } temp++; if (temp == index) { n.next = n.next.next; break ; } } } } public static void display() { for (CiNode n = first.next; n != first; n = n.next) { System.out.print(n.data + " " ); } System.out.println(); } public static void main(String[] args) { CiNode node4 = new CiNode( "ddd" , null ); CiNode node3 = new CiNode( "ccc" , node4); CiNode node2 = new CiNode( "bbb" , node3); CiNode node1 = new CiNode( "aaa" , node2); first = new CiNode( null , node1); node4.next = first; System.out.println( "当前链表:" ); display(); add( new CiNode( "eee" , null ), 5 ); // 传5进去是为了体现循环,当参数大于了链表长度时,又回到first System.out.println( "插入后链表:" ); display(); remove( 11 ); System.out.println( "删除后链表:" ); display(); } } |
循环单链表模拟击鼓传花游戏
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | public class JiGuChuanHua implements Runnable { private Object person; //游戏的人的data private JiGuChuanHua next; //指向下一个人, private static JiGuChuanHua first; //第一个人 public JiGuChuanHua() { super (); } //构造方法 public JiGuChuanHua(Object person, JiGuChuanHua next) { super (); this .person = person; this .next = next; } @Override public void run() { JiGuChuanHua loser = first; //以第一个人为起点 double time = (Math.random() + 0.5 ) * 10 ; //随机产生游戏时间(5-15s) boolean flag = true ; //结束线程的标志 System.out.println( "本局游戏时间:" + time + "s" ); System.out.println( "游戏开始:" ); System.out.println(loser.person); //初始游戏时,花在第一个人手上,打印 double startTime = System.currentTimeMillis(); //获取开始游戏的时间 while (flag) { for (JiGuChuanHua node = first;; node = node.next) { loser = node.next; //loser指向下一个人,模拟传花过程 System.out.println(loser.person); //打印拿到花的人 try { Thread.sleep(( long ) (Math.random() * 500 )); //线程睡眠,模拟花在每一个人手中停留时间 } catch (InterruptedException e) { e.printStackTrace(); } double endTime = System.currentTimeMillis(); //传完一个人时的时间 if (endTime - startTime >= time * 1000 ) { //游戏时间到,这里不具备原子性,所以是大于等于 flag = false ; //标志位置为false break ; } } } System.out.println( "游戏结束,拿到花的人是:" + loser.person); //打印最后拿到花的人 } public static void main(String[] args) { //将参加游戏的人用链表连起来,构成一个循环 JiGuChuanHua person5 = new JiGuChuanHua( "e" , null ); JiGuChuanHua person4 = new JiGuChuanHua( "d" , person5); JiGuChuanHua person3 = new JiGuChuanHua( "c" , person4); JiGuChuanHua person2 = new JiGuChuanHua( "b" , person3); JiGuChuanHua person1 = new JiGuChuanHua( "a" , person2); person5.next = person1; first = person1; JiGuChuanHua jgch = new JiGuChuanHua(); Thread thread = new Thread(jgch); thread.start(); //开启线程 } } |
二、双向循环链表
从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。一般我们都构造双向循环链表。
插入操作
删除操作
简单实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | public class CiDlNode { private Object data; private CiDlNode next; private CiDlNode prev; private static CiDlNode first; public CiDlNode() { super (); } public CiDlNode(Object data, CiDlNode next, CiDlNode prev) { super (); this .data = data; this .next = next; this .prev = prev; } public static void insert(Object data, int index) { CiDlNode node = new CiDlNode(data, null , null ); if (index == 0 ) { node.next = first.next; first.next.prev = node; first.next = node; node.prev = first; } else { int temp = 0 ; for (CiDlNode n = first.next;; n = n.next) { temp++; if (temp == index) { node.next = n.next; node.next = n.next; n.next.prev = node; n.next = node; node.prev = n; break ; } } } } public static void remove(Object data) { for (CiDlNode n = first.next; n != first; n = n.next) { if (n.data.equals(data)) { n.prev.next = n.next; n.next.prev = n; } } } public static void print() { for (CiDlNode node = first.next; node != first; node = node.next) { System.out.print(node.data + " " ); } System.out.println(); } public static void main(String[] args) { first = new CiDlNode( "0" , null , null ); CiDlNode node1 = new CiDlNode( "aaa" , null , first); CiDlNode node2 = new CiDlNode( "bbb" , null , node1); CiDlNode node3 = new CiDlNode( "ccc" , null , node2); CiDlNode node4 = new CiDlNode( "ddd" , first, node3); node3.next = node4; node2.next = node3; node1.next = node2; first.next = node1; System.out.println( "当前链表:" ); print(); insert( "ddd" , 5 ); System.out.println( "插入后链表:" ); print(); remove( "ddd" ); System.out.println( "删除后链表:" ); print(); } } |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步