关键:结束条件为当p->next == p,此时说明链表只剩下该结点了。
#include<stdio.h>
#include<stdlib.h>
typedef struct Lnode{
int data;
struct Lnode* next;
}Pnode;
Pnode* createnode(int n)
{
Pnode* head = (Pnode*)malloc(sizeof(Pnode));
head->data = 1;
head->next = NULL;
Pnode* r = head;
for(int i=2; i<=n; i++)
{
Pnode* s = (Pnode*)malloc(sizeof(Pnode));
s->data = i;
s->next = NULL;
r->next = s;
r = s;
}
r->next = head;
return head;
}
void findandkill(Pnode* head, int m)
{
Pnode* tail = head;
while(tail->next != head)
{
tail = tail->next;
}
Pnode* p = head;
while(p->next != p)
{
for(int i=1; i<m; i++)//本题1 2进循环 3不进入循环 第三个被删掉
{
tail = p;
p = p->next;
}
tail->next = p->next;
free(p);
p = tail->next;
}
printf("%d",p->data);
free(p);
}
int main()
{
int n, m;
scanf("%d%d",&n,&m);
Pnode* head = createnode(n);
findandkill(head, m);
return 0;
}
还有一个知识点:链表结点的删除:
for(int i=1; i<m; i++)
{
{
tail = p;
p = p->next;//找到两个一前一后的指针
}
tail->next = p->next;//将前一个指针指向后一个指针原本指向的位置,即前一个结点跳过了后一个结点和第三个结点相连了
free(p);//记得将跳过的那个结点内存清除
p = tail->next;//再次将两个结点回归一前一后的关系
}
利用链表思想,用数组实现:(理解)
#include<stdio.h>
int main()
{
int n,m;
printf("请输入有多少个人n:\n");
scanf("%d",&n);
printf("请输入淘汰数m:\n");
scanf("%d",&m);
int L[10000];///数组的长度为题目定的最大值
int i,j;
for (i=0;i<n;i++)
{
L[i]=i+1;
}
L[n-1]=0;//1 2 3 ... n-1 0
int cnt=n,count=1;
int p=0,q=0;
p=L[p];//p = 1
while(cnt!=1)
{
if (count%m==0)
{
L[q]=L[p];
printf("淘汰的人为:%d\n",p);
cnt--;
}
q=p;
p=L[p];
count++;
}
if (L[p]==0)
printf("剩下的人:%d",n);
else
printf("剩下的人:%d",L[p]);
}