这个题目是一个典型的约瑟夫问题,唯一特殊的地方是每次报的数M会一直改变而已。我感觉其实用普通的数组做也行,但是题目要求必须要用链表实现,因此正好趁着做这题的机会好好温习一下C语言中的结构体和指向结构体的指针。
以下是具体的代码实现,希望各位指教。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<conio.h>
/*
问题描述:
从1到n这n个人顺时针坐着,每个人手里拿着一个密码,第一轮初始一个密码,从第一个人开始,数到这个密码的人,报出自己的密码,
此人退出。从下一个人开始,依照刚才报出的密码再次筛选人退出,直到最后一个人。
第一个输入为人数,第二个输入为初始密码,接下来为每个人的密码。
使用循环链表实现。
输入:
6
3
6 5 4 3 2 1
输出:
3 1 4 2 5 6
注意!这里输出的是每个人的序号顺序
*/
//结构体定义
struct Node
{
int index;
int value;
int flag;
Node *next;
};
int main(void)
{
int numPeo;
int StartCode;
scanf("%d",&numPeo);
scanf("%d",&StartCode);
//初始化第一个节点
//这里是结构体指针的内存空间的初始化,使用malloc()函数必须要包含头文件<stdlib.h>
Node *head = (Node *)malloc(sizeof(Node));
head->flag = 0;
head->index = 1;
head->value = 0;
head->next = NULL;
scanf("%d",&(head->value));
//初始化剩余节点
Node *p = head;
for(int i = 2; i <= numPeo ;i++)
{
int eachcode;
scanf("%d",&eachcode);
Node *temp = (Node *)malloc(sizeof(Node));
temp->flag = 0;
temp->index = i;
temp->value = eachcode;
temp->next = NULL;
p->next = temp;
p = p->next;
}
//此时P指向的是链表最后一个元素,且其next指针为空,为获得循环链表,把P->next指向头元素
p->next = head;
int outNum = 0;//出列人数
int code = StartCode;//当前所需出列的序号
int i = 1;//当前报到的序号
while(outNum <= numPeo)
{
if(p->flag == 0)
{
if(i == code )
{
printf("%d",p->index);
code = p->value ;
i = 0; //当前序号清零
p->flag = 1;
outNum++;
}
//注意这里i的含义,切勿画蛇添足!
i++;
}
//循环控制
p = p->next;
}
getch();
return 0 ;
}