单向环形链表解决约瑟夫问题
约瑟夫问题:
设编号为1,2,… n的n个人围坐一圈,约定编号为k(1<=k<=n)的人从1开始报数,数到m 的那个人出列,它的下一位又从1开始报数,
数到m的那个人又出列,依次类推,直到所有人出列为止,由此产生一个出队编号的序列。
单向环形链表图示:

代码:
1 import lombok.Data; 2 import org.junit.Test; 3 import java.util.ArrayList; 4 import java.util.List; 5 6 public class JosephusRingTest { 7 @Test 8 public void test() { 9 RingSingleNode node1 = new RingSingleNode("小一"); 10 RingSingleNode node2 = new RingSingleNode("小二"); 11 RingSingleNode node3 = new RingSingleNode("小三"); 12 RingSingleNode node4 = new RingSingleNode("小四"); 13 RingSingleNode node5 = new RingSingleNode("小五"); 14 RingSingleLinkedList ringSingleLinkedList = new RingSingleLinkedList(); 15 ringSingleLinkedList.addNode(node1); 16 ringSingleLinkedList.addNode(node2); 17 ringSingleLinkedList.addNode(node3); 18 ringSingleLinkedList.addNode(node4); 19 ringSingleLinkedList.addNode(node5); 20 System.out.println("最初链表~~~~~共" + ringSingleLinkedList.size() + "个"); 21 ringSingleLinkedList.show(); 22 23 List<RingSingleNode> result = ringSingleLinkedList.JosephusRing(1, 2); 24 System.out.println(result); 25 System.out.println("最终链表~~~~~共" + ringSingleLinkedList.size() + "个"); 26 ringSingleLinkedList.show(); 27 } 28 } 29 30 @Data 31 class RingSingleNode { 32 33 /** 34 * 名称 35 */ 36 private String name; 37 38 private RingSingleNode next; 39 40 public RingSingleNode() { 41 42 } 43 44 public RingSingleNode(String name) { 45 this.name = name; 46 } 47 48 @Override 49 public String toString() { 50 return "RingSingleNode{" + 51 "name='" + name + '\'' + 52 '}'; 53 } 54 } 55 56 /** 57 * 单向环形链表 58 */ 59 class RingSingleLinkedList { 60 /** 61 * 链表的头部节点 62 */ 63 private RingSingleNode first; 64 65 /** 66 * 链表的尾部节点 67 */ 68 private RingSingleNode last; 69 70 /** 71 * 判断链表是否为空 72 * @return 73 */ 74 public boolean isEmpty() { 75 return first == null; 76 } 77 78 /** 79 * 添加节点 80 * @param newNode 81 * @return 82 */ 83 public boolean addNode(RingSingleNode newNode) { 84 if (isEmpty()) { 85 //添加第一个节点 86 first = newNode; 87 newNode.setNext(newNode); 88 last = newNode; 89 return true; 90 } 91 newNode.setNext(first); 92 last.setNext(newNode); 93 last = newNode; 94 return true; 95 } 96 97 /** 98 * 获取链表的长度 99 * @return 100 */ 101 public int size() { 102 int count = 0; 103 if (isEmpty()) { 104 return count; 105 } 106 107 RingSingleNode temp = first; 108 while (temp != last) { 109 count++; 110 temp = temp.getNext(); 111 } 112 count++; 113 return count; 114 } 115 116 /** 117 * 链表的遍历 118 */ 119 public void show() { 120 RingSingleNode temp = first; 121 while (temp != last) { 122 System.out.println(temp); 123 temp = temp.getNext(); 124 } 125 System.out.println(temp); 126 } 127 128 /** 129 * 约瑟夫环 130 * @param k 131 * @param m 132 * @return 133 */ 134 public List<RingSingleNode> JosephusRing(int k, int m) { 135 /* 136 设编号为1,2,… n的n个人围坐一圈,约定编号为k(1<=k<=n)的人从1开始报数, 137 数到m 的那个人出列,它的下一位又从1开始报数, 138 数到m的那个人又出列,依次类推, 139 直到所有人出列为止,由此产生一个出队编号的序列。 140 */ 141 List<RingSingleNode> result = new ArrayList<>(); 142 if (isEmpty()) { 143 System.out.println("链表为空,无法成环"); 144 return result; 145 } 146 147 if (k>=1 && k<=size() && m>=1) { 148 while (first != last) { 149 //first移动(k-1)步到达编号为k的节点,last移动(k-1)步到达新的尾节点 150 //报数之后,first和last一起走(m-1)步,first到达需弹出的节点,last则为弹出后的新的尾节点 151 //即first,last一起总计走(k + m - 2)步 152 for (int i = 0; i < k + m - 2; i++) { 153 first = first.getNext(); 154 last = last.getNext(); 155 } 156 //将指定节点弹出链表 157 result.add(first); 158 first = first.getNext(); 159 last.setNext(first); 160 } 161 //链表只剩最后一个节点 162 result.add(first); 163 first = null; 164 last = null; 165 return result; 166 } 167 System.out.println("m或k输入不合法"); 168 return result; 169 } 170 }

浙公网安备 33010602011771号