单向环形链表CircleSingleLinkedList
Josephu(约瑟夫、约瑟夫环问题)
Josephu 问题为:设编号为1,2,… n的n个人围坐一圈,约定编号k(1<=k<=n)的人从1开始报数,数到m 的那个人出列,它的下一位又从1开始报数,数到m的那个人又出列,依次类推,直到 所有人出列为止,由此产生一个出队编号的序列。
提示:用一个不带头结点的循环链表来处理Josephu 问题:先构成一个有n个结点的单循环链表,然后由k结点起从1开始计数,计到m时,对应结点从链表中删除,然后再从被删除结点的下一个结点又从1开始计数,直到最后一个结点从链表中删除,算法结束。
单向环形链表的节点
class Boy {
private int no
;
private Boy next
;
public int getNo() {
return no
;
}
public Boy
getNext() {
return next
;
}
public void setNo(int no
) {
this.no
= no
;
}
public void setNext(Boy next
) {
this.next
= next
;
}
public Boy(int no
) {
this.no
= no
;
}
}
创建单向环形链表
先创建第一个节点,让first指针指向该节点,形成环形每当创建一个节点,就把该节点加入到已有的环形链表中。curBoy.next=boy;boy.next=frist;
public void addBoy(int nums
) {
if (nums
< 1) {
System
.out
.println("num的值不正确");
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
;
}
}
}
遍历单向环形链表
让辅助指针curBoy指向frist节点通过while循环遍历该环形链表,curBoy.next==frist结束
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();
}
}
删除单向环形链表节点
删除节点,
first=firt.nexthelper.next=first
原来first指向的节点没有任何引用会被回收,即被删除。
在删除节点之前,需要将first和helper移动k-1次。
public void countBoy(int startNo
, int countNum
, int nums
) {
if (first
== null
|| startNo
< 1 || startNo
> nums
) {
System
.out
.println("数据输入有误");
return;
}
Boy helper
= first
;
while (true) {
if (helper
.getNext() == first
) {
break;
}
helper
= helper
.getNext();
}
for (int i
= 0; i
< startNo
- 1; i
++) {
first
= first
.getNext();
helper
= helper
.getNext();
}
while (true) {
if (helper
== first
) {
break;
}
for (int i
= 0; i
< countNum
- 1; i
++) {
first
= first
.getNext();
helper
= helper
.getNext();
}
System
.out
.printf("小孩节点%d出圈\n", first
.getNo());
first
= first
.getNext();
helper
.setNext(first
);
}
System
.out
.printf("最后留在圈中小孩编号%d\n", first
.getNo());
}
测试单向环形链表
package linkedlist
;
public class CirCleSingleLinkedListDemo {
public static void main(String
[] args
) {
CirCleSingleLinkedList cirCleSingleLinkedList
= new CirCleSingleLinkedList();
cirCleSingleLinkedList
.addBoy(5);
cirCleSingleLinkedList
.showBoy();
cirCleSingleLinkedList
.countBoy(1, 2, 5);
}
}
完整代码
package linkedlist
;
public class CirCleSingleLinkedListDemo {
public static void main(String
[] args
) {
CirCleSingleLinkedList cirCleSingleLinkedList
= new CirCleSingleLinkedList();
cirCleSingleLinkedList
.addBoy(5);
cirCleSingleLinkedList
.showBoy();
cirCleSingleLinkedList
.countBoy(1, 2, 5);
}
}
class CirCleSingleLinkedList {
private Boy first
= new Boy(-1);
public void addBoy(int nums
) {
if (nums
< 1) {
System
.out
.println("num的值不正确");
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();
}
}
public void countBoy(int startNo
, int countNum
, int nums
) {
if (first
== null
|| startNo
< 1 || startNo
> nums
) {
System
.out
.println("数据输入有误");
return;
}
Boy helper
= first
;
while (true) {
if (helper
.getNext() == first
) {
break;
}
helper
= helper
.getNext();
}
for (int i
= 0; i
< startNo
- 1; i
++) {
first
= first
.getNext();
helper
= helper
.getNext();
}
while (true) {
if (helper
== first
) {
break;
}
for (int i
= 0; i
< countNum
- 1; i
++) {
first
= first
.getNext();
helper
= helper
.getNext();
}
System
.out
.printf("小孩节点%d出圈\n", first
.getNo());
first
= first
.getNext();
helper
.setNext(first
);
}
System
.out
.printf("最后留在圈中小孩编号%d\n", first
.getNo());
}
}
class Boy {
private int no
;
private Boy next
;
public int getNo() {
return no
;
}
public Boy
getNext() {
return next
;
}
public void setNo(int no
) {
this.no
= no
;
}
public void setNext(Boy next
) {
this.next
= next
;
}
public Boy(int no
) {
this.no
= no
;
}
}