Java数据结构——循环链表
一、单向循环链表
表中的最后一个节点的指针域指向头结点,整个链表形成一个环。其他的与单链表相同。
(以下图片均来自网络,侵删)
插入操作
删除操作
简单实现
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(); } }
循环单链表模拟击鼓传花游戏
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(); //开启线程 } }
二、双向循环链表
从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。一般我们都构造双向循环链表。
插入操作
删除操作
简单实现
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(); } }