【数据结构与算法】约瑟夫环问题

约瑟夫环问题:

约瑟夫环是一个数学的应用问题:已知n个人(以编号1,2,3…n分别表示)围坐在一张圆桌周围。

从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;

依此规律重复下去,直到圆桌周围的人全部出列。

基本要求:用不带头结点的单循环连表作为数据元素的存储结

结点个数:8。即8个结点的编号1,2,3,4,5,6,7,8

随机报数值m = 2.

package cn.ls.ring.test;
/**
 * 
 *结点类
 */
public class Node {
	int code;  //结点值
	Node next; //下一个结点
	public Node() {
		super();
	}
	public Node(int code) {
		super();
		this.code = code;
	}
	Node(int code, Node nextVal){
		this.code = code;
		this.next = nextVal;
	}
	public boolean equals(Node node) {
		return code == node.code;
	}
}

package cn.ls.ring.test;
/**
 * 
 *约瑟夫环类
 */
public class JesephTest {
	//头指针
	Node head;
	//尾指针
	Node rear;
	//当前指针
	Node current;
	int size; 

	/**
	 * 删除
	 * @param m  随机报数值  逐个删除所有结点.
	 */
	private  void delete(int m){
		//从头结点开始.
		current = head;
		while(size > 0){
			//寻找第m个
			for (int i = 1; i<m; i++){
				current = current.next;
			}
			//输出被删除结点编号
			System.out.print(current.next.code+"  ");
			//被删结点脱链
			current.next = current.next.next;
			//从被删结点的下一个开始循环.
			current = current.next;
			size -- ;
		}
		head = rear = current = null;
	}
	/**
	 * 插入
	 * @param i  编号
	 * @param obj 元素
	 */
	private void insert(int i, Node obj){  
		//定位
		index(i-1);
		//设置第一次插入的指针值
		if(size == 0) head = rear = current = obj;
		//新节点加入连表
		obj.next = current.next;
		current.next = obj;
		//构成循环连表
		if(current.equals(rear)){
			obj.next = head;
			rear = obj;
		}else{
			rear.next = head;
		}
		size ++;
	}
	/**
	 * 定位
	 * @param i 编号
	 */
	private void index(int i) {
		if (i == -1)return ;
		current = head;//从头指针开始定位
		int j=0;
		while(current != null && j < i){
			current = current.next;
			j++;
		}
	}
	public static void main(String[] args) {
		JesephTest je = new JesephTest();
		je.insert(0, new Node(1)); 
		je.insert(1, new Node(2)); 
		je.insert(2, new Node(3)); 
		je.insert(3, new Node(4)); 
		je.insert(4, new Node(5)); 
		je.insert(5, new Node(6)); 
		je.insert(6, new Node(7)); 
		je.insert(7, new Node(8)); 
		Node curr = je.head;
		System.out.println("构建循环连表:");
		//查看循环连表是否构建完成
		for (int i = 0; i<je.size * 2 ; i++){
			System.out.print(curr.code+"  ");
			curr = curr.next;
		}
		System.out.println("\r依次被删结点编号为:");  
		je.delete(2);//随机报数值 = 2
	}
}

结果为:

测试是否构成循环链表:
1   2   3   4   5   6   7   8   1   2   3   4   5   6   7   8   
依次被删结点编号为:
3   6   1   5   2   8   4   7   

    原文作者:约瑟夫环问题
    原文地址: https://blog.csdn.net/yigelangmandeshiren/article/details/8266519
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞