Java数据结构--循环链表

Java数据结构–循环链表

在这里插入图片描述

循环链表类

public class CircularLinkList<T> {
    private class Node<T> {
        T date;
        Node next;

        public Node(T date, Node next) {
            this.date = date;
            this.next = next;
        }
    }

    private int length;
    private Node head;
    private Node rear;

    CircularLinkList() {
        head = new Node(null, null);
        head.next = head;
        rear = head;
        length = 0;
    }

    /**
     * 判断循环链表是否为空
     * @return true为空 false不为空
     */
    public boolean isEmpty() {
        return length == 0;
    }

    /**
     * 获得循环链表的长度
     * @return 循环链表的长度
     */
    public int size() {
        return length;
    }

    /**
     * 清空循环链表
     */
    public void clear() {
        head.next = head;
        head.date=null;
        length = 0;
    }

    /**
     * 向循环链表中加入一个值
     * @param t 待加入的值
     */
    public void put(T t) {
        if (isEmpty()) {
            head.date = t;
            length++;
        } else {
            Node<T> newNode = new Node<>(t, head);
            /*Node<T> tempNode = head;
            while (tempNode.next != head) {
                tempNode = tempNode.next;
            }
            if(length == 1){
            	head.next = newNode;
            }
            tempNode.next = newNode;
            length++;*/
            if(head == rear){
            	head.next = newNode;
            	rear = newNode;
            }else{
            	rear.next = newNode;
            	rear = rear.next;
            }
            length++;
        }
    }

    /**
     * 获取第i个元素的值
     * @param i 待查找元素的位置
     * @return 第i个节点的值
     * @Exception NullPointerException
     */
    public T get(int i){
        Node<T> newNode=null;
        if(i<length){
            Node<T> tempNode=head;
            for(int index=0;index<i;index++){
                tempNode=tempNode.next;
            }
            newNode=tempNode;
        }else{
            throw new NullPointerException("找不到该元素");
        }
        return newNode.date;
    }

    /**
     * 删除指定位置元素
     * @param i 待删除的元素的位置
     * @return 删除的值
     * @Exception NullPointerException
     */
    public T remove(int i) {
        Node<T> delNode=null;
        if(i<length){
            Node<T> tempNode=head.next;
            for(int index=0;index<i;i++){
                tempNode=tempNode.next;
            }
            delNode=tempNode.next;
            tempNode.next=delNode.next;
            length--;
        }else{
            throw new NullPointerException("没有可删除的元素");
        }
        return delNode.date;
    }
    public void removelNode(Node temp) {
        Node<T> tempNode = head;
        Node<T> p = rear;
        while(tempNode!=temp){  
        	p = tempNode;
        	tempNode = tempNode.next;
        }
        p.next = temp.next;
        length--;       
    }

    /**
     * 遍历循环链表
     */
    public void showList(){
    	int i = 0;
        if (isEmpty()){
            System.out.println("没有任何元素");
        }else{
            Node<T> tempNode=head;
            while(i<length){
                System.out.println(tempNode.date);
                tempNode=tempNode.next;
                i++;
            }
        }
    }

    /**
     *一个小游戏,约瑟夫问题
     * @return 游戏结果
     */
    public void playGame1(){
    	System.out.println("-------------");
        //StringBuilder sb=new StringBuilder();
        int count=1;
        Node<T> tempNode=head;
        while(length != 0){
            if(count!=3){
                tempNode=tempNode.next;
                count++;
            }else{
                // this.remove1(count);
                //showList();
                count=1;
                System.out.println("玩家"+tempNode.date+"出局"); 
                removelNode(tempNode);
                //sb.append("玩家"+tempNode.date+"出局"+"\n");                            
                tempNode=tempNode.next;
                
            }

        }
    }
}

测试类

public class CircularLinkListTest {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        CircularLinkList<String> circularLinkList=new CircularLinkList();
        System.out.println("请输入想要玩的人数");
        int counts = sc.nextInt();
        System.out.println("游戏开始,请输入你想坐的位置:");
        int seat = sc.nextInt();
        for (int i = 0; i < counts; i++) {
            if (i + 1 == seat) {
                circularLinkList.put("你");
            } else {
                circularLinkList.put("第" + i + "个犹太人");
            }
        }
        circularLinkList.showList();
        circularLinkList.playGame1();
    }
}

约瑟夫问题

在这里插入图片描述

约瑟夫问题是个有名的问题:N个人围成一圈,从第一个开始报数,第M个将被杀掉,最后剩下一个,其余人都将被杀掉。例如N=6,M=5,被杀掉的顺序是:6,4,5,2,1,3。
分析:
(1)由于对于每个人只有死和活两种状态,因此可以用布尔型数组标记每个人的状态,可用true表示死,false表示活。
(2)开始时每个人都是活的,所以数组初值全部赋为false。
(3)模拟杀人过程,直到所有人都被杀死为止。

public class JosephuTest {
    /*
     * 采用单链表的环形结构实现约瑟夫问题
     */
    public static void main(String[] args) {
        // 终端输入n,m数据,n为孩子数量,m为第几个编号退出
        Scanner scanner = new Scanner(System.in);
        CircleLinkList link = new CircleLinkList();
        String str = scanner.next();
        link.add(Integer.valueOf(str.split(",")[0]));// 生成单循环链表
        link.show();// 显示循环链表
        link.josephuTest(Integer.valueOf(str.split(",")[1]));// 输出踢出编号的顺序
    }

}

// 建立环形链表
class CircleLinkList{
    LinkNode firstNode = new LinkNode(0);// 一个单独的节点,用于指向循环链表第一个元素

    //添加数据
    public void add(int n) {
        // 判断输入的整数是否合理
        if (n < 1) {
            System.out.println("输入数据小于1,请重新输入");
            return;
        }
        // 遍历增加循环链表的每个元素
        LinkNode pre = firstNode;
        LinkNode p = null;
        for (int i = 1; i <= n; i++) {
            LinkNode tmp = new LinkNode(i);
            pre.next = tmp;
            pre = pre.next;
            p = tmp;
        }
        p.next = firstNode.next;// 头尾相连,生成循环链表
    }

    // 显示循环链表中的数据
    public void show() {
        if (firstNode.next == null) {
            System.out.println("请先输入数据");
            return;
        }
        // 遍历每个节点,并结合计算器判断是否遍历完成
        LinkNode tmp = firstNode.next;
        int count = 0;
        while (true) {
            if (tmp == firstNode.next && count > 0) {
                return;
            }
            System.out.println("小孩子的编号: " + tmp.num);
            count++;
            tmp = tmp.next;
        }
    }

    // 约瑟夫问题,n个孩子围成一个圈,从1开始报数,数到m时,去掉这个节点,并从1开始继续报数
    // 输出所有孩子的编号
    public void josephuTest(int m) {
        LinkNode tmp = firstNode.next;
        while (true) {
            // 循环到m节点的前一个节点,方便删除
            for (int i = 1; i <= m - 2; i++) {
                tmp = tmp.next;
            }

            if (tmp.next == tmp) {// 判断是否是最后一个节点
                System.out.print(tmp.num);
                return;
            } else {
                System.out.print(tmp.next.num + "->");
                tmp.next = tmp.next.next;// 删除报数为m的节点
                tmp = tmp.next;// 从下一个节点开始报数
            }
        }
    }
}

// 建立节点类
class LinkNode {
    int num;
    LinkNode next;
    // 初始函数,构造器
    LinkNode(int num) {
        this.num = num;
    }
}
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值