- 一.问题描述:
编号为1,2,3,,,n的n个人按顺时针方向围坐一圈,每人持有一个密码(正整数),一开始任选一个正整数作为报数上限值么,从第一个人开始顺时针自1开始报数,报到m时停止报数,报m的那个人出列,将他的密码作为新的密码m的值,从他的顺时针方向的下一个人开始重新从1报数,数到m的那个人出列,如此下去,直到所有的人全部出列。
- 二.方案设计:
这个问题的数据结构比较简单,只需将每个人的信息当成一个节点,结点中存放每个人的编号和密码,由于要反复做删除操作,所以采用单向循环链表比较方便。
- 三.基本步骤:
建立n个结点的单向循环链表;从链表的第一个结点起计数寻找第m个结点;输出该结点的id,将该结点的password作为新的m的值,删除该结点;根据m的值不断从链表中删除结点,直到链表为空。
- 四.代码实现
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
typedef struct node
{
int id; //编号
int password; //密码
struct node *next;
}Lnode;
Lnode *creat_LinkList()
{
Lnode *H = (Lnode*)malloc(sizeof(Lnode));
int n,i;
printf("请输入总人数: ");
scanf("%d",&n);
H->next=NULL;
Lnode *s,*r=H;
int num,mm;
for(i=1;i<=n;i++)
{
printf("请输入第%d个人的密码:",i);
scanf("%d",&mm);
s = (Lnode*)malloc(sizeof(Lnode));
s->id = i;
s->password = mm;
s->next=r->next;
r->next=s;
r=s;
}
s->next=H->next;
return H;
}
void Delete(Lnode *H,int ipassword)
{
Lnode *Pre=H->next,*Pnow=H->next,*Pdel;
int i=0,t=1;
while(Pre->next!=H->next)
Pre=Pre->next;
while(t)
{
for(i=1;i<ipassword;i++)
{
Pre=Pnow;
Pnow=Pnow->next;
}
if(Pre==Pnow) t=0;
Pdel=Pnow;
Pre->next=Pnow->next;
Pnow=Pnow->next;
ipassword=Pdel->password;
printf("退出队列的是:第<%d>个人,密码是:<%d>\n",Pdel->id,Pdel->password);
free(Pdel);
}
}
int main()
{
Lnode *H=NULL;
int initpassword;
H = creat_LinkList();
printf("请输入初始密码m: ");
scanf("%d",&initpassword);
Delete(H,initpassword);
}