环形链表
节点代码
class Node
{
public int ID { get; set; }
public Node Next { get; set; }
public Node(int iniID)
{
this.ID = iniID;
}
}
实现思路
在类体中创建一个 first 节点,使其永远指向链表的第一个节点,如果链表为空,则first指向为空
添加新的节点时,创建一个新的节点 cur,通过cur进行遍历,直到cur的next指向first,此时遍历到了链表的最后一个节点。然后添加如下代码
if(链表为空)
{
First = newNode;
newNode.next = First; //构成环
cur = first;
}
else
{
cur.next = newNode;
newNode = First; //构成环
cur = cur.next;
}
代码
//环形单向链表
class CircleSingleLinkedList
{
private Node First = null;
//添加 num 个节点到环中
public void Add(int num)
{
//检验num
if (num < 1)
{
Console.WriteLine("num 值不正确");
return;
}
Node cur = null; //辅助变量,帮助构建环形链表
//使用for循环来创建环形链表
for (int i = 1; i <= num; i++)
{
//根据编号创建节点
Node node = new Node(i);
//第一个节点需要特殊处理
if (i == 1)
{
First = node;
First.Next = First; //构成环
cur = First;
}
else
{
cur.Next = node;
node.Next = First;
cur = cur.Next;
}
}
}
//遍历
public void Traverse()
{
if (First == null)
{
Console.WriteLine("链表为空");
return;
}
var cur = First;
while (true)
{
Console.WriteLine($"节点编号:{cur.ID}");
if (cur.Next == First) //遍历完毕
{
break;
}
cur = cur.Next;
}
}
}
约瑟夫(Josephu)问题
题目描述
设编号为 1,2,3, … , n 的 n 个人坐成一圈
约定编号为k(1<=k<=n) 的人从1开始报数
数到m的那个人出列,他的下一位再从1开始报数,数到m的人再出列,依此类推,求出队顺序。
思路
1.创建一个辅助变量 helper 指向链表的最后一个节点(即First的前一个节点)
2.让First 和 helper 移动 k-1 次,得到起始位置
3.让First 和helper 移动 m-1 次,得到出队节点
4.将first出队 First = First.next; helper.next = First;
代码
/// <summary>
/// do something
/// </summary>
/// <param name="startNum">表示从第几个开始报数</param>
/// <param name="countNum">表示数几下</param>
/// <param name="num">表示最初有多少个节点</param>
public void SolveProblem(int startNum, int countNum, int num)
{
//校验数据
if (First == null || startNum < 1 || startNum > num)
{
Console.WriteLine("输入有误");
return;
}
//创建helper
var helper = First;
while (true)
{
if (helper.Next == First)
{
break;
}
helper = helper.Next;
}
//先让移动 k-1次
for (int i = 0; i < startNum - 1; i++)
{
First = First.Next;
helper = helper.Next;
}
//当报数时,让first和helper同时移动 m-1次,然后出圈
//直到圈中只有一个节点
while (true)
{
if (helper == First) //环形表中只剩一个节点
{
break;
}
for (int i = 0; i < countNum - 1; i++)
{
First = First.Next;
helper = helper.Next;
}
Console.WriteLine($"节点 [{First.ID}] 出圈");
First = First.Next;
helper.Next = First;
}
Console.WriteLine($"最后留在圈中的节点 [{First.ID}]");
}