概念
循环链表是另一种形式的链式存储结构。它的特点是表中最后一个结点的指针域指向头结点,整个链表形成一个环。
代码
节点对象
class Boy { private int no;// 编号 private Boy next; // 指向下一个节点,默认null public Boy(int no) { this.no = no; } public int getNo() { return no; } public void setNo(int no) { this.no = no; } public Boy getNext() { return next; } public void setNext(Boy next) { this.next = next; } }
// 创建一个环形的单向链表 class CircleSingleLinkedList { // 创建一个first节点,当前没有编号 private Boy first = null; // 添加小孩节点,构建成一个环形的链表 public void addBoy(int nums) { if(nums < 1){ System.out.println("数据不正确"); return; } Boy curBoy = null; for (int i = 1; i <= nums; i++){ Boy boy = new Boy(i); if(i == 1){ first = boy; first.setNext(first); curBoy = first; }else { curBoy.setNext(boy); boy.setNext(first); curBoy = boy; } } } // 遍历当前的环形链表 public void showBoy() { if(first == null){ System.out.println("没有任何小孩"); return; } Boy curBoy = first; while (true){ System.out.printf("小孩的编号%d \n",curBoy.getNo()); if(curBoy.getNext() == first){ break; } curBoy = curBoy.getNext(); } } }
案例
Josephu 问题为:设编号为1,2,… n的n个人围坐一圈,约定编号为k(1<=k<=n)的人从1开始报数,数到m 的那个人出列,它的下一位又从1开始报数,数到m的那个人又出列,依次类推,直到所有人出列为止,由此产生一个出队编号的序列。
代码
/** *根据用户的输入,计算出小孩出圈的顺序 * * @param startNo * 表示从第几个小孩开始数数 * @param countNum * 表示数几下 * @param nums * 表示最初有多少小孩在圈中 */ public void countBoy(int startNo, int countNum, int nums) { if( first == null || startNo < 1 || startNo > nums){ System.out.println("数据不合法"); return; } Boy temp = first; while (temp.getNext() != first){ temp = temp.getNext(); } //让first指向第一个小孩,temp指向最后一个 for(int i = 0; i < startNo - 1; i++){ first = first.getNext(); temp = temp.getNext(); } while (first != temp){ for (int i = 0; i < countNum - 1; i++){ first = first.getNext(); temp = temp.getNext(); } System.out.printf("小孩%d出圈\n",first.getNo()); first = first.getNext(); temp.setNext(first); } System.out.printf("最后留在圈中的小孩编号%d\n",first.getNo()); }
测试
CircleSingleLinkedList circleSingleLinkedList = new CircleSingleLinkedList(); circleSingleLinkedList.addBoy(5); circleSingleLinkedList.showBoy(); circleSingleLinkedList.countBoy(1,2,5);