前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >单向链表实现约瑟夫环

单向链表实现约瑟夫环

作者头像
JusterZhu
发布2022-12-07 20:14:35
2870
发布2022-12-07 20:14:35
举报
文章被收录于专栏:JusterZhuJusterZhu

构建一个单项的环形链表思路

  • 先创建第一个节点,让first指向该节点,并形成环形
  • 后面当我们每创建一个新的节点,就把该节点加入到已有的环形链表中即可。

遍历环形链表

  • 先让一个辅助指针(变量)currentNode,指向first节点
  • 然后通过一个while循环遍历该循环链表即可currentNode.next == first结束
代码语言:javascript
复制
public class PersonNode 
{
    public int Id { get; set; }

    public PersonNode(int id) 
    {
        Id = id;
    }

    public PersonNode NextPerson { get; set; }
}

/// <summary>
/// 创建一个环形的单向链表
/// </summary>
public class MyJoseph
{
    //创建一个头节点,不包含任何意义的数据
    private PersonNode first = new PersonNode(-1);

    /// <summary>
    /// 添加节点
    /// </summary>
    /// <param name="num">需要创建几个节点</param>
    public void addPerson(int num)
    {
        if (num <= 0) 
        {
            Console.WriteLine("num的值不正确");
            return;
        }

        //辅助指针帮助构建环形链表
        PersonNode currentNode = null;

        //使用for循环创建我们的环形链表
        for (int i = 1; i <= num; i++)
        {
            //根据编号创建节点
            PersonNode person = new PersonNode(i);

            //如果是第一个节点
            if (i==1)
            {
                first = person;
                first.NextPerson = first; //构成环形
                currentNode = first;//让currentNode指向第一个节点,因为fist节点不能动
            }
            else
            {
                //让当前节点指向新增加的节点
                currentNode.NextPerson = person;
                //将新增的节点指向第一个节点完成闭环
                person.NextPerson = first;
                //改变当前节点的位置
                currentNode = person;
            }
        }
    }

    public void Print() 
    {
        if (first == null)
        {
            Console.WriteLine("链表为空");
            return;
        }

        PersonNode currentNode = first;
        while (true)
        {
            Console.WriteLine($"编号{ currentNode.Id }");
            if (currentNode.NextPerson == first) break;
            currentNode = currentNode.NextPerson;
        }
    }

    /// <summary>
    /// 踢出圈
    /// </summary>
    /// <param name="startId">从第几个人开始踢</param>
    /// <param name="num">数几次</param>
    /// <param name="personNum">圈内总人数</param>
    public void Kill(int startId,int num,int personNum) 
    {
        if (first == null || startId < 1 || startId > personNum) {
            Console.WriteLine("参数有误");
            return;
        }

        PersonNode temp = first;

        //找到最后一个节点
        while (true)
        {
            //等式成立则代表遍历到最后
            if (temp.NextPerson == first) break;
            temp = temp.NextPerson;
        }

        //first 和 temp 向前移动一个节点
        for (int i = 0; i < startId - 1; i++)
        {
            first = first.NextPerson;
            temp = temp.NextPerson;
        }

        while (true)
        {
            if (temp == first) break;

            //从当前节点往后数,数出需要出圈的人
            for (int i = 0; i < num - 1; i++)
            {
                first = first.NextPerson;
                temp = temp.NextPerson;
            }
            Console.WriteLine($"Person出圈{ first.Id }");
            first = first.NextPerson;
            temp.NextPerson = first ;
        }
        Console.WriteLine($"最后留在圈中的Person{ first.Id }");
    }
}

//调用
MyJoseph myJoseph = new MyJoseph();
myJoseph.addPerson(5);
myJoseph.Print();
myJoseph.Kill(1,2,5);
myJoseph.Print();
Console.Read();
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2022-02-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 JusterZhu 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档