c#单向链表实现约瑟夫环


 

 

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

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

遍历环形链表

  • 先让一个辅助指针(变量)currentNode,指向first节点
  • 然后通过一个while循环遍历该循环链表即可currentNode.next == first结束

 

public class PersonNode
{
   public int Id { get; set; }

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

   public PersonNode NextPerson { get; set; }
}

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

   /// 
   /// 添加节点
   /// 
   /// 需要创建几个节点
   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;
      }
  }

   /// 
   /// 踢出圈
   /// 
   /// 从第几个人开始踢
   /// 数几次
   /// 圈内总人数
   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();