单向环装链表操作以及约瑟夫问题求解

1. 节点构建

//构建节点

class Item{
	private int no;
	private Item next;
	
	public Item(int no) {
		this.no = no;
	}
	public int getNo() {
		return no;
	}
	public void setNo(int no) {
		this.no = no;
	}
	public Item getNext() {
		return next;
	}
	public void setNext(Item next) {
		this.next = next;
	}
	@Override
	public String toString() {
		return "item [no=" + no + "]";
	}
}

2、约瑟夫链表构建

  • 代码
//构建josephu链表
class JosephuLinkList{
	//创建first指针,用于指向第一个节点
	Item first = null;
	
	//添加nums个节点
	public void add(int nums) {
		//对nums进行校验
		if(nums < 1) {
			System.out.println("添加个数不正确!");
		}else {
			//辅助指针,用于指向当前的节点
			Item curItem = null;
			for (int i = 1; i <= nums; i++) {
				Item item = new Item(i);
				if(i == 1) {//第一次添加
					first = item;
					item.setNext(item);
					curItem = item;
				}else {
					curItem.setNext(item);
					item.setNext(first);
					curItem = item;
				}
			}
		}
		
	}
	
	//遍历
	public void list() {
		if(first == null) {
			System.out.println("尚无节点!");
			return;
		}
		Item curItem = first;
		while (true) {
			System.out.printf("打印环装链表数据:item的no:%d\n",curItem.getNo());
			if(curItem.getNext() == first) {
				break;
			}else {
				curItem = curItem.getNext();
			}
		}
		
	}
	/**
	 * 
	 * @param startItem 第几个开始
	 * @param count 树几下
	 * @param nums  一共几个人
	 */
	public void countItems(int startItem,int count,int nums ) {
		//首先对数字进行校验
		if(startItem < 1||startItem > nums||nums < 1) {
			System.out.println("输入格式不正确!");
			return;
		}
		//定义辅助变量,指向环状链表尾部
		Item helper = first;
		while(true) {
			if(helper.getNext() == first) {
				break;
			}
			helper = helper.getNext();
		}
		
		//第几个开始 firse和helper 一起移动(startItem-1)下
		for(int i = 0; i < startItem-1; i++) {
			first = first.getNext();
			helper = helper.getNext();			
		}
		//开始循环数数并打印
		while(true) {
			if(first == helper) {
				break;
			}
			//数count下 firse和helper 一起移动(count-1)下
			for(int i = 0; i < count-1; i++) {
				first = first.getNext();
				helper = helper.getNext();			
			}
			
			//打印节点数据并删除节点
			System.out.printf("josephu打印数据:%d\n",first.getNo());
			//并删除节点
			first = first.getNext();
			helper.setNext(first);	
		}
		//打印最后一个节点
		System.out.printf("josephu打印数据:%d\n",first.getNo());
	}
}
  • 思路
1、首先定义输入参数:一共几个同学nums,从第几个开始startItem,每次数几下count;
2、定义辅助变量/指针:helper指向尾部,即first指针的前一个节点,作用:用于删除节点(helper指向待删除节点的前一个节点)
3、先让helper和firse指针同时移动(startItem-1)下,到开始同学的位置。
4、开始玩游戏,让同学数count下,同时first和helper指针移动(count-1)下,然后打印first指针指向节点的信息,然后删除first指针指向的节点:
first = first.next;
helper.next = first;
5、first指向的同学继续玩游戏,重复第四步骤,直到剩下最后一个同学。

3. 测试

  • 代码:
public class JosephuLinkListDemo {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		JosephuLinkList josephuLinkList = new JosephuLinkList();
		josephuLinkList.add(15);
		josephuLinkList.list();
		
		josephuLinkList.countItems(1,2,15);
	}
}
  • 测试结果:
打印环装链表数据:item的no:1
打印环装链表数据:item的no:2
打印环装链表数据:item的no:3
打印环装链表数据:item的no:4
打印环装链表数据:item的no:5
打印环装链表数据:item的no:6
打印环装链表数据:item的no:7
打印环装链表数据:item的no:8
打印环装链表数据:item的no:9
打印环装链表数据:item的no:10
打印环装链表数据:item的no:11
打印环装链表数据:item的no:12
打印环装链表数据:item的no:13
打印环装链表数据:item的no:14
打印环装链表数据:item的no:15
josephu打印数据:2
josephu打印数据:4
josephu打印数据:6
josephu打印数据:8
josephu打印数据:10
josephu打印数据:12
josephu打印数据:14
josephu打印数据:1
josephu打印数据:5
josephu打印数据:9
josephu打印数据:13
josephu打印数据:3
josephu打印数据:11
josephu打印数据:7
josephu打印数据:15
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值