算法练习之约瑟夫环

实验目的:掌握循环单链表的生成及插入删除的实现方法和应用。

实验内容:已知nn>=1)个人围坐一圆桌周围,从序号位k的人开始报数,顺时针数到m的那个人出列;它的下一个人又从1开始报数,数到m的那个人有出列;依次规则重复去,直到剩下1人为止。

方法说明:

1、构造长度为n,数据分别为(123n)的不

带头节点的单循环链表。

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.







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值