实验目的:掌握循环单链表的生成及插入删除的实现方法和应用。
实验内容:已知n(n>=1)个人围坐一圆桌周围,从序号位k的人开始报数,顺时针数到m的那个人出列;它的下一个人又从1开始报数,数到m的那个人有出列;依次规则重复去,直到剩下1人为止。
方法说明:
1、构造长度为n,数据分别为(1,2,3,…,n)的不
带头节点的单循环链表。
2、找到第一个出发点k。
3、数到m,删除此节点,继续数,直到删完所有节点。
约瑟夫(Josephu)问题改造:
每个人持有一张正整数密码,当某个人出列时,将她的
密码作为新的m值,从下一个人在开始数,如此,直到
全部出列。
解决问题的核心步骤:(程序的基本算法)
⒈建立一个具有n个链结点,无头结点的循环链表;
⒉确定第1个报数人的位置;
⒊不断地从链表中删除链结点,直到链表为空。
随便从网上找了一下,发现真是全是无脑复制, 一下子我还以为我对题目的理解错了呢。
一。结点类
public class Node<T> {
public T data;
public Node<T> next;
public Node(T data, Node<T> next) {
this.data = data;
this.next = next;
}
public Node() {
this(null, null);
}
public Node(T d){
data=d;
next=null;
}
}
直接引用上次做栈省下的代码
约瑟夫环;
public class Josephu {
private Node<Integer> head;
public Josephu() {
this(50);
}
public Josephu(int n) {
Node<Integer> q, rear;
int i = 1;
head = new Node<Integer>(i);
head.next = head;
rear = head;
while (i < n) {
i++;
q = new Node<Integer>(i,head);
rear.next = q;
rear = q;
}
}
public void Run(int s, int d) {
int j = 0;
Node<Integer> p = head;
while (j < s - 1) {
j++;
p = p.next;
}
while (p.next != p) {
j = 1;
while (j < d-1) {
j++;
p = p.next;
}
delete(p);
p = p.next;
this.output();
}
}
private void delete(Node<Integer> p) {
// TODO Auto-generated method stub
Node<Integer> q = p.next; // q是p的后继结点
System.out.print("delete: " + q.data + " ");
if (q == head) // 欲删除head指向结点时,
head = q.next; // 要将head向后移动
p.next = q.next; // 删除q
}
public void output() // 输出单向链表的各个结点值
{
Node<Integer> p = head;
System.out.print(this.getClass().getName() + ": ");
do {
System.out.print(p.data + " -> ");
p = p.next;
} while (p != head);
System.out.println();
}
}
大部分还是抄的,坦白说,但是网上大多都是错的。我改好了。估计老师也知道网上肯定有,所以还加了一个附加题,不过这个算法倒是挺简单的、
下面我解决一下附加题。
为结点类加一个属性
private int password;
将约瑟夫环的构造函数改为如下
public Josephu(int n) {
Node<Integer> q, rear;
int i = 1;
head = new Node<Integer>(i);
head.next = head;
rear = head;
while (i < n) {
i++;
q = new Node<Integer>(i, head);
q.setPassword((int)(Math.random()*n));
rear.next = q;
rear = q;
}
}
这样即使不用密码也可正常运转,只增加一个set方法/
改造run方法使其一法两用
public void Run(int s, int d,boolean normal) {
int j = 0;
int t = d;
Node<Integer> p = head;
while (j < s - 1) {
j++;
p = p.next;
}
while (p.next != p) {
j = 1;
while (j < t- 1) {
j++;
p = p.next;
}
delete(p);
if(!normal){t=p.getPassword();}
p = p.next;
this.output();
}
}
ok.