问题描述已知n个人(以编号1,2,3…n分别表示)围坐在一张圆桌周围。从编号为1的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。要求输出最后一位出列的人的序号。
一般来说是41个人,报到3出列
思考过程当我遍历整个序列到尾部的时候,我需要把指针重新指向整个序列的头部。如果用数组来做做,只需要令k=(k+1)%len就能实现序列的循环。这里我们利用一种数据结构–>单向循环链表来做。虽说思想比较简单,但是基本涵盖了链表的基本知识。
还是建议(包括我自己)不要去网络上找代码,一定要回到书本,网上部分人的代码是错误的或者说思路比较清奇,对于基础知识不牢靠的同学来说是一种致命打击
下面给出代码
#include<stdio.h>
#include<malloc.h>
//定义结构体
typedef struct Node{
int num;//这里存的是每个人最初的序号
struct Node *next;
}Node,*PNode;
//初始化链表
void init(int n,PNode &head){
head = (PNode)malloc(sizeof(Node));
head->num=1;
//头插法
/* PNode temp;
head->num = 1;
head->next=head;
for(int i=n;i>=2;i--){//给每个人一个序号
temp=(PNode)malloc(sizeof(Node));
temp->num = i;
temp->next = head->next;
head->next = temp;
}
*/
//尾插法
PNode tail=head;
PNode p;
for(int i=2;i<=n;i++){
p = (PNode)malloc(sizeof(Node));
p->num = i;
p->next=head;
tail->next = p;
tail=p;
}
}
//删除节点
void deleteNode(PNode &p){
PNode temp = p->next;
p->next = p->next->next;
free(temp);
}
void write(PNode head){
PNode p = head;
while(p->next!=head){
printf("%d ",p->num);
p=p->next;
}
printf("%d ",p->num);
}
int getlen(PNode head){
int len = 1;
PNode p = head;
while(p->next!=head){
len++;
p=p->next;
}
return len;
}
int main(){
int n,m;//n为总人数,m为需出列的序号
scanf("%d%d",&n,&m);
PNode p;
init(n,p); //初始化单向需循环链表
printf("总人数为:%d\n",getlen(p));
PNode head=p; //用来遍历链表
int count=0;//用来标记序号
while(n>2){
count++;// 0 41 69 88 101 110 116 119 120
if((count+1)%m==0){ //定位到要删除节点的前驱
printf("%d ",head->next->num);
deleteNode(head);
n--;
count++;
}
head=head->next;
}
printf("\n");
//**不能使用p指针,实际上p指针很可能在运算过程中丢失了**
printf("剩余人数为%d\n",getlen(head));
write(head);
return 0;
}