链表之报数问题
描述
有n个人围成一圈,顺序从1开始排号。从第1个人开始报数(从1到3报数),凡报到3的人退出圈子,问最后留下的是原来第几号的那位。建议用循环链表实现。
链表节点结构体:
typedef struct Node
{
int num;
struct Node* next;
};
输入
只有一个正整数n,(其中n的范围n>=3,n<=1000)。
输出
输出最后留下的人是原来的第几号。
请注意行尾输出换行。
输入样例 1
10
输出样例 1
4
输入样例 2
50
输出样例 2
11
算法概要:定义环形链表(双向),每当数到3后,将这一节点从链表中去除。
当节点的下一节点等于其自身时,只剩下该节点,退出循环,即找到了最后一人。
具体算法呈现如下:
#include<stdio.h>
#include<stdlib.h>
struct node{
int num;
struct node *next;
struct node *previous;
};
struct node * create(int a)
{ struct node *head,*p1,*p2;
int n,i;
head=NULL;
for(i=1;i<=a;i++)
{
p1=(struct node*)malloc(sizeof(struct node));
p1->num=i;
if(head==NULL) head=p2=p1;
else{
p2->next=p1;
p1->previous=p2;
p2=p1;
}
}
if(head!=NULL)
p2->next=head;
head->previous=p2;
return head;
}
void mod(struct node *head,int n)
{ struct node *p=head,*t;
int count=1;
while(p->next!=p)
{ p=p->next;
count+=1;
if(count==3)
{ count=1;
(p->previous)->next=p->next;
(p->next)->previous=p->previous;
t=p;
p=p->next;
t->next=NULL;
}
}
printf("%d",p->num);
}
void free_list(struct node *head)
{ struct node *p;
while(head!=NULL)
{ p=head;
head=head->next;
free(p);
}
}
int main(void)
{ int n;
scanf("%d",&n);
struct node *p;
p=create(n);
mod(p,n);
free_list(p);
}