选首领------循环链表实现

来源:互联网 发布:未来软件 编辑:程序博客网 时间:2024/06/18 14:04

此题是在软考的书上看到的,想起以前推到过一个公式,那个超级简单,但是这个是循环链表实现的。有助于学习数据结构。

问题是:

选首领。N个游戏者围成一圈,从第一个人开始顺序报数1,2,3.凡是报道3者推出圈子,最后留在圈子的人为首领。

求首领是?


解题分析:很明显的是约瑟夫问题,可以先先创建一个循环链表,然后设置两个变量计数器一个  c  计算数到第几个,还有一个   k  记录还剩多少个,每次当 c 的值等于二的时候输出后面的数,当  k  的值等于1的时候返回,说明还剩最后一个很明显是答案。


代码:
#include <iostream>
#include <cstdio>
#include <stdlib.h>
using namespace std;
typedef struct node{
int code; /*游戏者的编号*/
struct node *next;
}NODE,*LinkList;
LinkList create_list(int n) /*创建一个节点数为n的单循环链表,返回值为游戏编号为1的节点的指针*/
{
LinkList head,p;
int i;
head=(NODE*)malloc(sizeof(NODE));
if(!head)
{
cout<<"memory allocation error!"<<endl;
return NULL;
}
head->code=1;
for(i=n;i>1;i--)/*尾插法创建循环链表的其余n-1个节点*/
{
p=(NODE*)malloc(sizeof(NODE));
if(!p)
{
cout<<"memory allocation error!"<<endl;
return NULL;
}
p->code=i;
p->next=head->next;
head->next=p;
}
return head;
}
void output(LinkList head) /*输出链表中节点的数据*/
{
LinkList p;
p=head;
do
{
cout<<(p->code);
p=p->next;
}while(p!=head);
printf("\n");
}
void play(LinkList head,int n) /*选首领*/
{
LinkList p,q;
int c=0,k;
p=head;
c=1;
k=n;
while(k>1)
{
if(c==2) /*当c等于2的时候,p指向的节点后继即为将被删除的节点*/
{
q=p->next;
p->next=q->next;
printf("%4d",p->code);
free(q);
c=0;
k--;
}
else
{
c++;
p=p->next;
}
}
printf("\n%4d was the winner.",p->code);  /*输出最后留在圈子内的人的编号*/
}


int main()
{
LinkList head;
int n;
printf("input the number of players:");
scanf("%d",&n);
head=create_list(n);/*创建单循环链表*/
if(head)
{
output(head);
play(head,n);
}
return 0;
}


0 0