一、单向环形链表

单向环形链表-约瑟夫问题
如图,链表的最后一个节点的next指向链表的第一个节点,形成一个环形链表。

二、单向环形链表使用场景-约瑟夫问题

josephu(约瑟夫、约瑟夫环)问题:
设编号为1,2,3…n的 n个人坐成一圈,编号为k(1<=k<=n )的人从1开始报数,数到m的那个人出列, 他的下一位继续从1开始报数,数到m的那个人又出列,依次类推,直到所有人出列为止,由此产生一个出队编号的序列。
单向环形链表-约瑟夫问题

三、约瑟夫问题分析

用一个不带头节点的单向环形链表来实现:

  • 首先生成一个 带有 n 个节点的单向环形链表;

  • 报数前准备就绪:
    由于是单向环形链表,只能通过next指针向后移动,因此,在某个节点出队时,想要要将链表继续连接成环,就需要出队列的那个节点的前一个节点作为辅助。
    1)Child first = null;
    Child helper = null;
    创建 first 变量,指向第一个节点,遍历整个单向环形链表,找到最后一个节点,创建辅助变量,指向最后一个节点(first前面的那个节点)。
    单向环形链表-约瑟夫问题
    单向环形链表-约瑟夫问题
    2) 由于编号为k的人第一个开始从1报数,在真正开始报数前,需要将first指针和helper指针向前移动 k-1次,让first指向编号为k的人(helper始终保持在first的前一个节点)。
    单向环形链表-约瑟夫问题

  • 循环遍历链表,开始报数并出队列
    1)编号为k的人开始从1报数,数到m的人出队列,
    单向环形链表-约瑟夫问题
    单向环形链表-约瑟夫问题
    first节点和helper节点均向后移动 m-1次,此时first指向要删除的节点。
    first = first.next;
    helper.next = first;
    2)当 helper == first,说明链表中已经剩最后一个节点。

四、代码实现

相关文章: