单向循环链表—约瑟夫问题

班级活动中,一个班n人围成一圈玩游戏时,从某一个人开始数数,当数到m的那个人必须表演一个节目,同时这个人退出游戏。如何安排位置,能使自己避免表演节目呢? 此类问题与约瑟夫问题是同一类问题。

    有名的约瑟夫问题:N个人围成一圈,从第一个开始报数,第M个将被杀掉,最后剩下一个,其余人都将被杀掉。例如N=5,M=2,被杀掉的人的序号为2,4,1,5;最后只留下3。

  此类问题都可以用单循环链表给以解决。结点包含当前的序号和指向下一序号(或者说结点)的指针。建好整个单循环链表后,从头结点开始遍历,同时开始计数(Count=1开始),当Count=m-1时,删除第m个结点(即序号为m的结点将会受到惩罚)。循环最终只余下一个结点。

   本文参考http://blog.csdn.net/createchance/article/details/17426469博客进一步给出详细的理解。 

第一步,建立单循环链表

typedef struct node  
{  
    int data;  
    struct node *next;  
}node,*pNode;  
pNode List_init(int n)
{
int i;  
    pNode temp;  
    pNode head = InsertNode(1);  
  
    for(i =n; i>1; i--) 
{  
        temp = InsertNode(i);  
        temp->next = head->next;  
        head->next = temp;  
    }  
    return head; 
}
  
pNode InsertNode(int n)  
{  
    pNode p = NULL;  
    p = (pNode)malloc(sizeof(pNode));  
    p->data = n;  
    p->next = p;  
    return p;  
} 


本文以N=5为例,上述代码实现如下单循环链表


第二步,从list(文中为编号为1的结点)开始,开始计数。当Count=m-1时,删除第m个结点(即序号为m的结点将会受到惩罚)。代码如下

pNode List_begin(pNode list,int m)  
{  
    int count;  
    pNode temp = NULL;  
  
    for(count=1;list->next!=list;count++)
{  
        if(count == m-1) 
{  
            temp = list->next;  
            list->next = temp->next;  
            count = 0;  
            List_show(list);  
        }  
        list = list->next;  
    }  
    return list;  
}  
  
void List_show(pNode list)  
{  
    pNode p = list;  
    if(list == NULL) 
{
        exit(-1);  
}
    do
{  
        printf("%3d",p->data);  
        p = p->next;  
    }while(list!= p);  
    printf("\n");  
}  


  当N=5,M=3时,m-1=2

当第一次count=2时,此时list指向序号为2的结点,删除序号为3的结点(到序号为3的结点时,计数值count必为3),删掉后遍历链表,输出值为

2,4,5,1

而后情况类似。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值