• 重新整理数据结构与算法——环形链表[五]


    前言

    有一个需求:

    上面这张图,要求数到数数,比如说数2,如果数到2,那个人就退出去,其他人继续数,问最后留在圈子里面的人是谁?

    这个可以用环形链表实现。

    正文

    思路

    1.首先要形成一个环形链表。

    2.第二个就是要想到如何删除一个节点。

    3.如何最优判断删除剩下最后一个节点。

    其实看过在三中介绍了,链表要删除一个节点,最好的方法就是知道它的前一个结点,然后只要把他的前一个节点的next,重置给当前要删除的next即可,这样就从链表中删除了。

    所以需要两个引导项,一个是当前小孩,一个是当前小孩的前一个。

    那么什么时候判断为最后一个节点呢?

    就是这两个引导项相同的时候。

    代码

    public class Josepfu
    {
    	public Children first;
    
    	public int numbers;
    
    	public void showBoy()
    	{
    		if (first == null)
    		{
    			Console.WriteLine("无任何小孩!");
    		}
    		Children curBoy = first;
    		while (true)
    		{
    			Console.Write(curBoy.number+"   ");
    			if (curBoy.next == first)
    			{
    				break;
    			}
    			curBoy = curBoy.next;
    		}
    		Console.WriteLine();
    	}
    	/// <summary>
    	/// 初始化小孩个数
    	/// </summary>
    	/// <param name="numbers"></param>
    	public void addChilds(int numbers) {
    		this.numbers = numbers;
    		// 校验数据不对
    		if (numbers < 1)
    		{
    			throw new Exception("你输入的数据不能小于1!");
    		}
    		Children curBoy = null;
    		for (int i = 1; i <= numbers; i++)
    		{
    			var child = new Children(i);
    			if (i == 1){
    				//初始化第一个节点
    				first = child;
    				first.next = first;
    				curBoy = first;
    			}
    			else {
    				curBoy.next = child;
    				child.next = first;
    				curBoy = child;
    			}
    		}
    	}
    	/// <summary>
    	/// 数数弹出小孩函数
    	/// </summary>
    	/// <param name="startNo">从哪个小孩开始数</param>
    	/// <param name="count">报数是多少</param>
    	public void outChild(int startNo,int count) {
    		if (numbers == 0)
    		{
    			throw new Exception("你还没有初始化小孩!");
    		}
    		if (startNo < 1&&startNo>numbers)
    		{
    			throw new Exception("报数小孩不存在");
    		}
    		//特殊情况判断
    		if (first.next == first)
    		{
    			Console.WriteLine(first.number);
    			return;
    		}
    		// 初始化一个引导小孩
    		Children helper = first;
    		while (true)
    		{
    			if (helper.next == first)
    			{
    				break;
    			}
    			helper = helper.next;
    		}
    		// 定位到第一个报数小孩
    		for (int i = 0; i < startNo-1; i++)
    		{
    			first = first.next;
    			helper = helper.next;
    		}
    		//开始报数
    		while (true)
    		{
    			if (first == helper)
    			{
    				break;
    			}
    			//自己要数一下
    			for (int i = 0; i < count-1; i++)
    			{
    				first = first.next;
    				helper = helper.next;
    			}
    			first = first.next;
    			helper.next = first;
    		}
    		Console.WriteLine(first.number);
    	}
    }
    
    public class Children {
    
    	public int number;
    
    	public Children next;
    
    	public Children(int number,Children next)
    	{
    		this.number = number;
    		this.next = next;
    	}
    
    	public Children(int number):this(number,null)
    	{
    	}
    }
    

    测试

    static void Main(string[] args)
    {
    	Josepfu josepfu = new Josepfu();
    	josepfu.addChilds(7);
    	josepfu.showBoy();
    	josepfu.outChild(1,2);
    	Console.ReadKey();
    }
    

    结果

    下一节

    整理的排序算法不晓得到哪里去了,后面是查询算法,之后再回到排序算法。

  • 相关阅读:
    2-4 Vue中的属性绑定和双向数据绑定
    MySQL索引失效的几种情况
    MySQL索引失效的几种情况
    Linux实现MYSQl数据库的定时备份
    Linux实现MYSQl数据库的定时备份
    你还在 Select * 吗?
    你还在 Select * 吗?
    世界顶级的程序员们告诉你:这些书都是你应该读的
    世界顶级的程序员们告诉你:这些书都是你应该读的
    真正努力和不努力的程序员,发朋友圈究竟有什么不一样?
  • 原文地址:https://www.cnblogs.com/aoximin/p/13083938.html
Copyright © 2020-2023  润新知