zoukankan      html  css  js  c++  java
  • 数据结构(五)-环形链表及约瑟夫问题

    一、单向环形链表的应用场景(约瑟夫问题)

    Josephu 问题为:设编号为1,2, ... n 的 n 个人坐成一圈,约定从编号为 k(n≥k≥1) 的人开始报数,数到 m 的那个人出列,她的下一位又从 1 开始报数,数到 m 的那个人又出列,以此类推,直到所有人出圈为止,因此形成一个出圈编号的序列

    二、单向链表的示意图

    三、创建环形链表图解

    创建环形链表代码实现

    // 创建单向环形链表
    class SingleCircularLinkedList{
    	
    	// 初始化一个头节点
    	Girl first = null;
    	
    	// 添加数据到链表中
    	public void add(int num) {
    		// 校验参数
    		if(num < 1) {
    			System.out.println("您输入的小孩个数小于1,不能创建环形链表");
    		}
    		// 定义临时指针
    		Girl curGirl = first;
    		for(int i = 1; i <= num; i++) {
    			Girl girl = new Girl(i);
    			
    			if(i == 1) { // 说明是第一个节点
    				first = girl;
    				first.setNext(first);
    				curGirl = first;
    			}else {
    				curGirl.setNext(girl);
    				curGirl = girl; // curGirl 后移
    				curGirl.setNext(first); // 形成闭环
    			}
    		}
    	}
    	
    	// 遍历链表
    	public void list() {
    		// 判断链表是否为空
    		if(first == null) {
    			System.out.println("当前链表为空");
    			return;
    		}
    		// 定义临时指针
    		Girl curGirl = first;
    		while(true) {
    			System.out.printf("小孩编号为 %d 
    ", curGirl.getNo());
    			if(curGirl.getNext() == first) {
    				break;
    			}
    			curGirl = curGirl.getNext();
    		}
    	}
    }
    
    // 创建节点类
    class Girl {
    
    	private int no;
    	private Girl next;
    
    	public Girl(int no) {
    		super();
    		this.no = no;
    	}
    
    	public int getNo() {
    		return no;
    	}
    
    	public void setNo(int no) {
    		this.no = no;
    	}
    
    	public Girl getNext() {
    		return next;
    	}
    
    	public void setNext(Girl next) {
    		this.next = next;
    	}
    }
    

    四、约瑟夫问题图解

    补充,设置 helper 节点的思路来源于单向链表删除节点时,指针始终指在当前节点的前一位,cur.next = cur.next.next
    代码实现

    	// 约瑟夫问题
    	public void joseph(int startNo, int countNum, int nums) {
    		// 参数校验
    		if(startNo < 1 || countNum > nums || nums < 1) {
    			System.out.println("输入的参数有误");
    			return;
    		}
    		// 定义临时指针
    		Girl helper = first;
    		// 让helper移动到first的上一个节点的位置,让first指针移动到startNo处(移动startNo - 1次)
    		while(true) {
    			if(helper.getNext() == first) {
    				break;
    			}
    			helper = helper.getNext();
    		}
    		
    		for(int i = 0; i < startNo - 1; i++) {
    
    			first = first.getNext();
    			helper = helper.getNext();
    		}
    		
    		// 让first和helper同时移动countNum - 1次,小孩出圈
    		while(true) {
    			if(helper == first) { // 条件成立说明圈中只有一个小孩
    				break;
    			}
    			for(int i = 0; i < countNum - 1; i++) {
    				first = first.getNext();
    				helper = helper.getNext();
    			}
    			// 小孩出圈操作
    			System.out.printf("出圈的小孩为  %d 号
    ", first.getNo());
    			first = first.getNext();
    			helper.setNext(first);
    		}
    		// 输出圈中留下的lucky girl
    		System.out.printf("留在圈中的 lucky girl 为  %d 号
    ", first.getNo());
    	}
    
  • 相关阅读:
    微信小程序-默认选中状态
    微信小程序-翻页(优化)
    openLayers3 中实现多个Overlay
    2月的最后一天
    2月27日
    杂记--写于狂风乱作的夜晚
    安装部署程序
    superMap Object 属性查看的一点代码
    坚持不懈的学习吧,少年
    Windows API中几个函数的总结
  • 原文地址:https://www.cnblogs.com/wsilj/p/13689060.html
Copyright © 2011-2022 走看看