1. 问题描述:

    设编号为1,2,…,n的n个人围坐一圈,约定编号为k(1 <=k <=n)的人从1开始报数,数到m的那个人出列,它的下一位又从1开始报数,数到m的那个人又出列,依次类推,直到所有人出列为止,由此产生一个出队编号的序列。

 

2. 分析: 该问题可以使用多种数据结构, 但是比较简单和自然的做法是利用一个具有n个链接点且不带头接点的循环链表.

 

3. 实现:

  1) 建立循环链表:

 

代码
    public class CirculaLinkedNode<T>
    {
        
public T Data { setget; }
        
public CirculaLinkedNode<T> Next { setget; }
    }

    
public class CirculaLinkedList<T>
    {
        
public CirculaLinkedNode<T> Head { setget; }

        
public CirculaLinkedList(CirculaLinkedNode<T> head)
        {
            
this.Head = head;
        }

        
public CirculaLinkedList(T[] data)
        {
            
if (data == null || data.Length < 1)
            {
                
throw new ArgumentNullException("data");
            }

            CirculaLinkedNode
<T> head = new CirculaLinkedNode<T>
            {
                Data 
= data[0],
                Next 
= null
            };
            CirculaLinkedNode
<T> currentNode = head, node = null;
            
for (int i = 1; i < data.Length; i++)
            {
                node 
= new CirculaLinkedNode<T>
                {
                    Data 
= data[i],
                    Next 
= null
                };
                currentNode.Next 
= node;

                currentNode 
= node;
            }
            currentNode.Next 
= head;

            
this.Head = head;
        }

        
public void Remove(CirculaLinkedNode<T> node)
        {
            
if (this.Head == null)
            {
                
return;
            }

            
if (this.Head.Equals(node))
            {
                
if (Head.Next.Equals(Head))
                {
                    Head 
= null;
                }
                
else
                {
                    var n 
= Head.Next;
                    
while (!n.Next.Equals(Head))
                    {
                        n 
= n.Next;
                    }
                    n.Next 
= Head.Next;
                    Head 
= Head.Next;
                }
            }
            
else
            {
                var n 
= Head;
                
while (!n.Next.Equals(Head))
                {
                    
if (n.Next.Equals(node))
                    {
                        n.Next 
= n.Next.Next;
                        
break;
                    }

                    n 
= n.Next;
                }
            }            
        }

        
public CirculaLinkedNode<T> GetNodeByValue(T value)
        {
            var node 
= this.Head;
            
while (!node.Next.Equals(Head))
            {
                
if (node.Data.Equals(value))
                {
                    
return node;
                }

                node 
= node.Next;
            }

            
return null;
        }
    }

 

   2) 实现Josephu解决方案:

 

代码
        /// <summary>
        
/// Josephy Problem
        
/// </summary>
        
/// <param name="n">N people</param>
        
/// <param name="m"></param>
        
/// <param name="k"></param>
        public static void Josephu(int n, int m, int k)
        {
            
if (n < 1)
            {
                
throw new ArgumentOutOfRangeException("n");
            }
            
if (m < 1)
            {
                
throw new ArgumentOutOfRangeException("m");
            }
            
if (k < 1 || k > n)
            {
                
throw new ArgumentOutOfRangeException("k");
            }

            
int[] personArray = new int[n];
            
for (int i = 0; i < n; i++)
            {
                personArray[i] 
= i + 1;
            }

            CirculaLinkedList
<int> cList = new CirculaLinkedList<int>(personArray);
            var firstNode 
= cList.GetNodeByValue(k);
            var node 
= firstNode;
            
while (cList != null && cList.Head != null)
            {
                
for (int i = 1; i < m; i++)
                {
                    node 
= node.Next;
                }
                Console.Write(
"---> {0}", node.Data);
                firstNode 
= node.Next;
                cList.Remove(node);
                node 
= firstNode;
            }
            Console.WriteLine(
"");
        }

    3) 测试:

 

CirculaLinkedListAction.Josephu(843);

 

 download