zoukankan      html  css  js  c++  java
  • 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();
    }
    }
  • 相关阅读:
    PAT T1001 Battle Over Cities-Hard Version
    PAT甲级2019冬季考试题解
    L3-016 二叉搜索树的结构
    PAT A1135 Is It A Red Black Tree
    PAT A1114 Family Property
    PAT A1034 Head Of Gang
    PAT A1151 LCA in Binary Tree
    什么是一揽子交易
    子公司自购买日(或合并日)开始持续计算的可辨认净资产(对母公司的价值)与购买日子公司可辨认净资产的公允价值有什么区别
    借少数股东权益,贷少数股东损益
  • 原文地址:https://www.cnblogs.com/ericz2j/p/10475853.html
Copyright © 2011-2022 走看看