转载——用C#学数据结构(5)
链表(续)
约瑟夫环问题。
http://379910987.blog.163.com/blog/static/335237972011621115036785/
public static LinkedList<int> JosephusRing(int n, int m,int k)
{
LinkedList<int> J1 = new LinkedList<int>();
for (int i = 0; i < n; i++)
J1.AddLast(i + 1);
LinkedList<int> J2 = new LinkedList<int>();
LinkedListNode<int> p=J1.First;
int t = 1;
while (J2.Count < n)//开始报数
{
if (t % m == 0)//需要出列
{
t = 1;
//用一个链表保存,并出列
int temp = p.Value;
if ((temp + k) % n == 0)
J2.AddLast(n);
else
J2.AddLast((temp+k)%n);
if (p == J1.Last)//末尾就指向链表表头
p = J1.First;
else//否则移向下一个节点
p = p.Next;
//根据值删除原节点
J1.Remove(temp);
}
else//不需要出列
{
t++;
//向后移动节点
if (p == J1.Last)//末尾就指向链表表头
p = J1.First;
else//否则移向下一个节点
p = p.Next;
}
}
return J2;
}
上面的这段程序采用的是删除值的方法,好处是只需要一个类似指针的变量标记当前节点,但是缺点是删除采用的是Remove(value),该方法会删除值的第一个匹配项,所以对于有相同值的情况下就显得不太好,虽然许多时候我们可以使用GetHashCode等方式保证值的唯一性,但是总是让人有点不放心,最好的办法是直接删除节点,而不是转个弯通过值删除节点。下面是改进的方法,只是多引入了一个节点变量:
public static LinkedList<int> JosephusRing(int n, int m,int k)
{
LinkedList<int> J1 = new LinkedList<int>();
for (int i = 0; i < n; i++)
J1.AddLast(i + 1);
LinkedList<int> J2 = new LinkedList<int>();
LinkedListNode<int> p=J1.First;
LinkedListNode<int> outer;//出列者
//移动到从k开始
for (int i = 0; i < k - 1; i++)
{
if(p==J1.Last)
p=J1.First;
else
p=p.Next;
}
while (J2.Count < n)
{
//先报数
for (int i = 1; i <m; i++)
{
if (p == J1.Last)
p = J1.First;
else
p = p.Next;
}
outer = p;//此时刚好报到m
J2.AddLast(outer.Value);
//移动到下一位
if (p == J1.Last)
p = J1.First;
else
p = p.Next;
J1.Remove(outer);
//将其移出链表,注意不能是J1.Remove(p);否则p不能指向链表中的节点了
}
return J2;
}
附截图:
浙公网安备 33010602011771号