对有n个人围成的一个圆圈进行按报数规则全部取数出列

设有n个人围成一个圆圈,现从第s个人开始报数,数到第m的人出列,然后从出列的下一个人重新开始报数,数到第m个人再出列,如此反复,直到所有的人全部出列为止。对于任意给定的n,s,m,求按出列次序得到的n个人员的序列。


首先,创建一个循环链表,这里默认头指针中的data为1,即为n个人中的第一个人


typedef int elemtype;
typedef struct node
{
elemtype data;
struct node *next;
}LinkList;

LinkList * Create()
{ LinkList * head;
LinkList *p,*tail;
elemtype x;
head=(LinkList *)malloc(sizeof(LinkList));
if(head==NULL)return head;

head->data=1;
head->next=head;
tail=head;
printf("请输入数据,从2开始,输入0为结束:\n");
scanf("%d",&x);
while(x!=0)
{
    p=(LinkList *)malloc(sizeof(LinkList));
    if(p==NULL)return head;
    p->data=x;
    tail->next=p;
    tail=p;
    scanf("%d",&x);

}
tail->next=head;
return head;}

出列算法:
第一:找到第s个报数的人:
LinkList * Find(LinkList *head,int s)
{
LinkList *p=head;
int count=1;
while(p)
{
if(count==s)
break;
else
{
p=p->next;
++count;
}
}
return p;}
第二:找到第m个人出列,并将报数起点设为m的下一个人:
int OutPut(LinkList *head,int m)
{

//循环做法
LinkList *p=head,*q;
if(p==NULL)return -1;
int i;
while(p->data!=p->next->data)
{
    for(i=1;i<m-1;i++)
        p=p->next;
    q=p->next;//记录取出点
    printf("\t%d",q->data);
    p->next=q->next;
    free(q);//删除取出点
    p=p->next;//报数点
}
printf("\t%d",p->data);
return 0;}

主函数:

int main(){
LinkList * head=Create();
LinkList *p=Find(head,2);
OutPut(p,2);
printf(“\n”);
return 0;}

这道题可以使用循环链表来实现,具体步骤如下: 1. 创建一个循环链表链表中节点的值为1~n,节点之间通过next指针相互连接成环。 2. 找到从第s个人开始报数的节点,将其设为当前节点。 3. 从当前节点开始,依次数m个节点,将第m个节点删除。 4. 将当前节点指向被删除节点的下一个节点。 5. 重复步骤3~4,直到链表中只剩下一个节点。 6. 输出所有出列的节点值,即为按出列次序得到的n个人员的序。 代码实现如下: ``` #include <stdio.h> #include <stdlib.h> // 定义循环链表节点结构体 typedef struct Node { int value; // 节点值 struct Node* next; // 指向下一个节点的指针 } Node; int main() { int n, s, m; printf("请输入n、s、m的值:"); scanf("%d%d%d", &n, &s, &m); // 创建循环链表 Node* head = (Node*)malloc(sizeof(Node)); head->value = 1; Node* p = head; for (int i = 2; i <= n; i++) { Node* node = (Node*)malloc(sizeof(Node)); node->value = i; p->next = node; p = node; } p->next = head; // 将尾节点指向头节点,形成环 // 找到从第s个人开始报数的节点 for (int i = 1; i < s; i++) { head = head->next; } p = head; // 删除节点,直到链表中只剩下一个节点 while (p->next != p) { // 依次数m个节点 for (int i = 1; i < m - 1; i++) { p = p->next; } // 删除第m个节点 Node* q = p->next; p->next = q->next; printf("%d ", q->value); free(q); // 将当前节点指向被删除节点的下一个节点 p = p->next; } // 输出最后一个节点 printf("%d\n", p->value); free(p); return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值